From: Sumeet Ungratwar Date: Mon, 13 Aug 2012 13:48:55 +0000 (-0700) Subject: Adding a general doc for traits provided in folly/Traits.h X-Git-Tag: v0.22.0~1170 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=636f38ca19dd9a0ba60787e59e215f3789961e7a;p=folly.git Adding a general doc for traits provided in folly/Traits.h Summary: Understood how traits are implemented in folly/Traits.h and added examples on how to use them. Test Plan: no specific tests Reviewed By: andrei.alexandrescu@fb.com FB internal diff: D546631 --- diff --git a/folly/Traits.h b/folly/Traits.h index 566036bb..84c7132c 100644 --- a/folly/Traits.h +++ b/folly/Traits.h @@ -41,7 +41,7 @@ namespace folly { * } * * void move2(T * from, T * to) { - * memcpy(from, to, sizeof(T)); + * memcpy(to, from, sizeof(T)); * } * * Most C++ types are relocatable; the ones that aren't would include @@ -73,7 +73,7 @@ template struct IsRelocatable : boost::mpl::not_ > * When using it with a template type, use it like this: * * // Make sure you're at namespace ::folly scope - * template + * template * FOLLY_ASSUME_RELOCATABLE(MyType) */ #define FOLLY_ASSUME_RELOCATABLE(...) \ @@ -89,7 +89,7 @@ template struct IsRelocatable : boost::mpl::not_ > * When using it with a template type, use it like this: * * // Make sure you're at namespace ::boost scope - * template + * template * FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyType) */ #define FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(...) \ diff --git a/folly/docs/Traits.md b/folly/docs/Traits.md new file mode 100644 index 00000000..b3761629 --- /dev/null +++ b/folly/docs/Traits.md @@ -0,0 +1,175 @@ + 'folly/Traits.h' + ----------------- + + Implements traits complementary to those provided in + + * Implements `IsRelocatable` trait. + * Implements `IsOneOf` trait + * Macros to state the assumptions easily + + ### Motivation + *** + + is the Boost type-traits library defining a + variety of traits such as `is_integral` or `is_floating_point`. This helps + to gain more information about a given type. + Many traits introduced by Boost have been standardized in C++11. + + folly/Traits.h implements traits complementing those present in boost. + + + ### IsRelocatable + *** + + In C++, the default way to move an object is by + calling the copy constructor and destroying the old copy + instead of directly copying the memory contents by using memcpy(). + The conservative approach of moving an object assumes that the copied + object is not relocatable. + The two following code sequences should be semantically equivalent for a + relocatable type: + + ```Cpp + { + void conservativeMove(T * from, T * to) { + new(to) T(from); + (*from).~T(); + } + } + + { + void optimizedMove(T * from, T * to) { + memcpy(to, from, sizeof(T)); + } + } + ``` + + Very few C++ types are non-relocatable. + The type defined below maintains a pointer inside an embedded buffer and + hence would be non-relocatable. Moving the object by simply copying its + memory contents would leave the internal pointer pointing to the old buffer. + + ```Cpp + class NonRelocatableType { + private: + char buffer[1024]; + char * pointerToBuffer; + ... + public: + NonRelocatableType() : pointerToBuffer(buffer) {} + ... + }; + ``` + + We can optimize the task of moving a relocatable type T using memcpy. + IsRelocatable::value describes the ability of moving around memory + a value of type T by using memcpy. + + ### Usage + *** + + * Declaring types + ```Cpp + template + class MyParameterizedType; + + class MySimpleType; + ``` + + * Declaring a type as relocatable + + Appending the lines below after definition of My*Type + (`MyParameterizedType` or `MySimpleType`) will declare it as relocatable + + ```Cpp + /* Definition of My*Type goes here */ + // global namespace (not inside any namespace) + namespace folly { + // defining specialization of IsRelocatable for MySimpleType + template <> + struct IsRelocatable : boost::true_type {}; + // defining specialization of IsRelocatable for MyParameterizedType + template + struct IsRelocatable> + : ::boost::true_type {}; + } + ``` + + * To make it easy to state assumptions for a regular type or a family of + parameterized type, various macros can be used as shown below. + + * Stating that a type is Relocatable using a macro + + ```Cpp + // global namespace + namespace folly { + // For a Regular Type + FOLLY_ASSUME_RELOCATABLE(MySimpleType); + // For a Parameterized Type + FOLLY_ASSUME_RELOCATABLE(MyParameterizedType); + } + ``` + + * Stating that a type has no throw constructor using a macro + + ```Cpp + namespace boost { + // For a Regular Type + FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MySimpleType); + // For a Parameterized Type + FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyParameterizedType); + } + ``` + + `fbvector` only works with relocatable objects. If assumptions are not stated + explicitly, `fbvector` or `fbvector` + will fail to compile due to assertion below: + + ```Cpp + BOOST_STATIC_ASSERT( + IsRelocatable::value + ); + ``` + + FOLLY_ASSUME_FBVECTOR_COMPATIBLE*(type) macros can be used to state that type + is relocatable and has nothrow constructor. + + * Stating that a type is `fbvector-compatible` using macros + i.e. relocatable and has nothrow default constructor + + ```Cpp + // at global level, i.e no namespace + // macro for regular type + FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MySimpleType); + // macro for types having 2 template parameters (MyParameterizedType) + FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyParameterizedType); + ``` + + Similary, + * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(MyTypeHavingOneParameter) macro is + for family of parameterized types having 1 parameter + * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(MyTypeHavingThreeParameters) macro is + for family of parameterized types having 3 parameters + * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(MyTypeHavingFourParameters) macro is + for family of parameterized types having 4 parameters + + * Few common types, namely `std::basic_string`, `std::vector`, `std::list`, + `std::map`, `std::deque`, `std::set`, `std::unique_ptr`, `std::shared_ptr`, + `std::function`, `boost::shared_ptr` which are compatible with `fbvector` + are already instantiated and declared compatible with `fbvector`. + `fbvector` can be directly used with any of these C++ types. + + * `std::pair` can be safely assumed to be compatible with `fbvector` if both + of its components are. + + ### IsOneOf + *** + + boost::is_same::value can be used to test if types of T1 and T2 are + same. folly::IsOneOf::value can be used to test if type of T1 + matches the type of one of the other template parameter, T1, T2, ...Tn. + Recursion is used to implement this type trait. + + if boost::is_integral::value == 1 and boost::is_integral::value == 1 + then folly::IsOneOf::value will return 1 +