folly: add bser encode/decode for dynamic
[folly.git] / folly / docs / Traits.md
1 'folly/Traits.h'
2 -----------------
3
4 Implements traits complementary to those provided in <boost/type_traits.h>
5
6   * Implements `IsRelocatable` trait.
7   * Implements `IsOneOf` trait
8   * Macros to state the assumptions easily
9
10 ### Motivation
11 ***
12
13 `<boost/type_traits.hpp>` is the Boost type-traits library defining a 
14 variety of traits such as `is_integral` or `is_floating_point`. This helps 
15 to gain more information about a given type.
16 Many traits introduced by Boost have been standardized in C++11.
17
18 `folly/Traits.h` implements traits complementing those present in boost. 
19
20
21 ### IsRelocatable
22 ***
23
24 In C++, the default way to move an object is by 
25 calling the copy constructor and destroying the old copy 
26 instead of directly copying the memory contents by using memcpy(). 
27 The conservative approach of moving an object assumes that the copied 
28 object is not relocatable. 
29 The two following code sequences should be semantically equivalent for a
30 relocatable type:
31
32 ```Cpp
33 {
34   void conservativeMove(T * from, T * to) {
35     new(to) T(from);
36     (*from).~T();
37   }
38 }
39
40 {
41   void optimizedMove(T * from, T * to) {
42     memcpy(to, from, sizeof(T));
43   }
44 }
45 ```
46
47 Very few C++ types are non-relocatable.
48 The type defined below maintains a pointer inside an embedded buffer and 
49 hence would be non-relocatable. Moving the object by simply copying its 
50 memory contents would leave the internal pointer pointing to the old buffer.
51
52 ```Cpp
53 class NonRelocatableType {
54 private:
55   char buffer[1024];
56   char * pointerToBuffer;
57   ...
58 public:
59   NonRelocatableType() : pointerToBuffer(buffer) {}
60   ...
61 };
62 ```
63
64 We can optimize the task of moving a relocatable type T using memcpy. 
65 IsRelocatable<T>::value describes the ability of moving around memory 
66 a value of type T by using memcpy.
67
68 ### Usage
69 ***
70
71   * Declaring types
72
73     ```Cpp
74     template <class T1, class T2>
75     class MyParameterizedType;
76
77     class MySimpleType;
78     ```
79
80   * Declaring a type as relocatable
81
82     Appending the lines below after definition of My*Type 
83     (`MyParameterizedType` or `MySimpleType`) will declare it as relocatable
84
85     ```Cpp
86     /* Definition of My*Type goes here */
87     // global namespace (not inside any namespace)
88     namespace folly {
89       // defining specialization of IsRelocatable for MySimpleType
90       template <>
91       struct IsRelocatable<MySimpleType> : boost::true_type {};
92       // defining specialization of IsRelocatable for MyParameterizedType
93       template <class T1, class T2>
94       struct IsRelocatable<MyParameterizedType<T1, T2>>
95           : ::boost::true_type {};
96     }
97     ```
98
99   * To make it easy to state assumptions for a regular type or a family of 
100     parameterized type, various macros can be used as shown below.
101
102   * Stating that a type is Relocatable using a macro
103
104     ```Cpp
105     // global namespace
106     namespace folly {
107       // For a Regular Type
108       FOLLY_ASSUME_RELOCATABLE(MySimpleType);
109       // For a Parameterized Type
110       FOLLY_ASSUME_RELOCATABLE(MyParameterizedType<T1, T2>);
111     }
112     ```
113
114   * Stating that a type has no throw constructor using a macro
115
116     ```Cpp
117     namespace boost {
118       // For a Regular Type
119       FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MySimpleType);
120       // For a Parameterized Type
121       FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyParameterizedType<T1, T2>);
122     }
123     ```
124
125 `fbvector` only works with relocatable objects. If assumptions are not stated 
126 explicitly, `fbvector<MySimpleType>` or `fbvector<MyParameterizedType>` 
127 will fail to compile due to assertion below:
128
129 ```Cpp
130 BOOST_STATIC_ASSERT(
131   IsRelocatable<My*Type>::value
132 );
133 ```
134
135 FOLLY_ASSUME_FBVECTOR_COMPATIBLE*(type) macros can be used to state that type 
136 is relocatable and has nothrow constructor.
137
138   * Stating that a type is `fbvector-compatible` using macros
139     i.e. relocatable and has nothrow default constructor
140
141     ```Cpp
142     // at global level, i.e no namespace
143     // macro for regular type
144     FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MySimpleType);
145     // macro for types having 2 template parameters (MyParameterizedType)
146     FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyParameterizedType);
147     ```
148
149 Similarly, 
150
151   * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(MyTypeHavingOneParameter) macro is 
152     for family of parameterized types having 1 parameter
153
154   * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(MyTypeHavingThreeParameters) macro is 
155     for family of parameterized types having 3 parameters
156
157   * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(MyTypeHavingFourParameters) macro is 
158     for family of parameterized types having 4 parameters
159
160 Few common types, namely `std::basic_string`, `std::vector`, `std::list`,
161 `std::map`, `std::deque`, `std::set`, `std::unique_ptr`, `std::shared_ptr`,
162 `std::function`, `boost::shared_ptr` which are compatible with `fbvector` are
163 already instantiated and declared compatible with `fbvector`. `fbvector` can be
164 directly used with any of these C++ types.
165
166 `std::pair` can be safely assumed to be compatible with `fbvector` if both of
167 its components are.
168
169 ### IsOneOf
170 ***
171
172 `boost::is_same<T1, T2>::value` can be used to test if types of T1 and T2 are 
173 same. `folly::IsOneOf<T, T1, Ts...>::value` can be used to test if type of T1 
174 matches the type of one of the other template parameter, T1, T2, ...Tn.
175 Recursion is used to implement this type trait.