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