Get ObserverManager compiling under MSVC
[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 static_assert(IsRelocatable<My*Type>::value, "");
131 ```
132
133 FOLLY_ASSUME_FBVECTOR_COMPATIBLE*(type) macros can be used to state that type 
134 is relocatable and has nothrow constructor.
135
136   * Stating that a type is `fbvector-compatible` using macros
137     i.e. relocatable and has nothrow default constructor
138
139     ```Cpp
140     // at global level, i.e no namespace
141     // macro for regular type
142     FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MySimpleType);
143     // macro for types having 2 template parameters (MyParameterizedType)
144     FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyParameterizedType);
145     ```
146
147 Similarly, 
148
149   * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(MyTypeHavingOneParameter) macro is 
150     for family of parameterized types having 1 parameter
151
152   * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(MyTypeHavingThreeParameters) macro is 
153     for family of parameterized types having 3 parameters
154
155   * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(MyTypeHavingFourParameters) macro is 
156     for family of parameterized types having 4 parameters
157
158 Few common types, namely `std::basic_string`, `std::vector`, `std::list`,
159 `std::map`, `std::deque`, `std::set`, `std::unique_ptr`, `std::shared_ptr`,
160 `std::function`, `boost::shared_ptr` which are compatible with `fbvector` are
161 already instantiated and declared compatible with `fbvector`. `fbvector` can be
162 directly used with any of these C++ types.
163
164 `std::pair` can be safely assumed to be compatible with `fbvector` if both of
165 its components are.
166
167 ### IsOneOf
168 ***
169
170 `boost::is_same<T1, T2>::value` can be used to test if types of T1 and T2 are 
171 same. `folly::IsOneOf<T, T1, Ts...>::value` can be used to test if type of T1 
172 matches the type of one of the other template parameter, T1, T2, ...Tn.
173 Recursion is used to implement this type trait.