From 93b0f543f20b8ef3a4c1e34591370011e2dc7168 Mon Sep 17 00:00:00 2001 From: Nicholas Ormrod Date: Wed, 5 Dec 2012 13:15:57 -0800 Subject: [PATCH] Added two new traits and a way to specify them Summary: Added IsBits (has value semantics; can be copied by memcpy and deleted by free. Implies IsRelocatable) and Is0Initializable (new (ptr) T() is equivalent to memset(ptr, 0, sizeof(T))). Converted the boost types for IsRelocatable to std types (now available from ). Added a new way to specify IsRelocatable, IsBits, and Is0Initializable: typedef std::true_type in your class. No namespace exiting required. This method also supports inheritance, and may be overriden in base classes. Added a test file to test Traits. Test Plan: Run new test file. Compile some real-world code (in my case, multifeed). Reviewed By: andrei.alexandrescu@fb.com FB internal diff: D610996 --- folly/Traits.h | 69 ++++++++++++++++++++++++++--- folly/test/TraitsTest.cpp | 93 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 folly/test/TraitsTest.cpp diff --git a/folly/Traits.h b/folly/Traits.h index 84c7132c..f2a517f2 100644 --- a/folly/Traits.h +++ b/folly/Traits.h @@ -19,11 +19,15 @@ #ifndef FOLLY_BASE_TRAITS_H_ #define FOLLY_BASE_TRAITS_H_ +#include +#include + +#include + #include #include +#include #include -#include -#include namespace folly { @@ -57,9 +61,64 @@ namespace folly { * types. You may want to add your own specializations. Do so in * namespace folly and make sure you keep the specialization of * IsRelocatable in the same header as SomeStruct. + * + * You may also declare a type to be relocatable by including + * `typedef std::true_type IsRelocatable;` + * in the class header. + * + * It may be unset in a base class by overriding the typedef to false_type. + */ +/* + * IsTriviallyCopyable describes the value semantics property. C++11 contains + * the type trait is_trivially_copyable; however, it is not yet implemented + * in gcc (as of 4.7.1), and the user may wish to specify otherwise. */ -template struct IsRelocatable : boost::mpl::not_ > -{}; +/* + * IsZeroInitializable describes the property that default construction is the + * same as memset(dst, 0, sizeof(T)). + */ + +namespace traits_detail { + +#define FOLLY_HAS_TRUE_XXX(name) \ + BOOST_MPL_HAS_XXX_TRAIT_DEF(name); \ + template struct name ## _is_true \ + : std::is_same {}; \ + template struct has_true_ ## name \ + : std::conditional< \ + has_ ## name ::value, \ + name ## _is_true, \ + std::false_type \ + >:: type {}; + +FOLLY_HAS_TRUE_XXX(IsRelocatable) +FOLLY_HAS_TRUE_XXX(IsZeroInitializable) +FOLLY_HAS_TRUE_XXX(IsTriviallyCopyable) + +#undef FOLLY_HAS_TRUE_XXX +} + +template struct IsTriviallyCopyable + : std::integral_constant::value || + // TODO: add alternate clause is_trivially_copyable, when available + traits_detail::has_true_IsTriviallyCopyable::value + > {}; + +template struct IsRelocatable + : std::integral_constant::value || + // TODO add this line (and some tests for it) when we upgrade to gcc 4.7 + //std::is_trivially_move_constructible::value || + IsTriviallyCopyable::value || + traits_detail::has_true_IsRelocatable::value + > {}; + +template struct IsZeroInitializable + : std::integral_constant::value || + traits_detail::has_true_IsZeroInitializable::value + > {}; } // namespace folly @@ -77,7 +136,7 @@ template struct IsRelocatable : boost::mpl::not_ > * FOLLY_ASSUME_RELOCATABLE(MyType) */ #define FOLLY_ASSUME_RELOCATABLE(...) \ - struct IsRelocatable< __VA_ARGS__ > : ::boost::true_type {}; + struct IsRelocatable< __VA_ARGS__ > : std::true_type {}; /** * Use this macro ONLY inside namespace boost. When using it with a diff --git a/folly/test/TraitsTest.cpp b/folly/test/TraitsTest.cpp new file mode 100644 index 00000000..ae13d66d --- /dev/null +++ b/folly/test/TraitsTest.cpp @@ -0,0 +1,93 @@ +/* + * Copyright 2012 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "folly/Benchmark.h" +#include "folly/Traits.h" + +#include +#include + +using namespace folly; +using namespace std; + +struct T1 {}; // old-style IsRelocatable, below +struct T2 {}; // old-style IsRelocatable, below +struct T3 { typedef std::true_type IsRelocatable; }; +struct T4 { typedef std::true_type IsTriviallyCopyable; }; +struct T5 : T3 {}; + +struct F1 {}; +struct F2 { typedef int IsRelocatable; }; +struct F3 : T3 { typedef std::false_type IsRelocatable; }; +struct F4 : T1 {}; + +namespace folly { + template <> struct IsRelocatable : std::true_type {}; + template <> FOLLY_ASSUME_RELOCATABLE(T2); +} + +TEST(Traits, scalars) { + EXPECT_TRUE(IsRelocatable::value); + EXPECT_TRUE(IsRelocatable::value); + EXPECT_TRUE(IsRelocatable::value); + EXPECT_TRUE(IsRelocatable::value); +} + +TEST(Traits, containers) { + EXPECT_TRUE (IsRelocatable>::value); + EXPECT_FALSE((IsRelocatable>::value)); + EXPECT_TRUE ((IsRelocatable>::value)); + EXPECT_TRUE (IsRelocatable>::value); +} + +TEST(Traits, original) { + EXPECT_TRUE(IsRelocatable::value); + EXPECT_TRUE(IsRelocatable::value); +} + +TEST(Traits, typedefd) { + EXPECT_TRUE (IsRelocatable::value); + EXPECT_TRUE (IsRelocatable::value); + EXPECT_FALSE(IsRelocatable::value); + EXPECT_FALSE(IsRelocatable::value); +} + +TEST(Traits, unset) { + EXPECT_FALSE(IsRelocatable::value); + EXPECT_FALSE(IsRelocatable::value); +} + +TEST(Traits, bitprop) { + EXPECT_TRUE(IsTriviallyCopyable::value); + EXPECT_TRUE(IsRelocatable::value); +} + +TEST(Traits, bitAndInit) { + EXPECT_TRUE (IsTriviallyCopyable::value); + EXPECT_FALSE(IsTriviallyCopyable>::value); + EXPECT_TRUE (IsZeroInitializable::value); + EXPECT_FALSE(IsZeroInitializable>::value); +} + +int main(int argc, char ** argv) { + testing::InitGoogleTest(&argc, argv); + google::ParseCommandLineFlags(&argc, &argv, true); + if (FLAGS_benchmark) { + folly::runBenchmarks(); + } + return RUN_ALL_TESTS(); +} + -- 2.34.1