2 * Copyright 2012 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 // @author: Andrei Alexandrescu
19 #ifndef FOLLY_BASE_TRAITS_H_
20 #define FOLLY_BASE_TRAITS_H_
22 #include <boost/type_traits.hpp>
23 #include <boost/mpl/and.hpp>
24 #include <boost/mpl/not.hpp>
26 #include <bits/c++config.h>
31 * IsRelocatable<T>::value describes the ability of moving around
32 * memory a value of type T by using memcpy (as opposed to the
33 * conservative approach of calling the copy constructor and then
34 * destroying the old temporary. Essentially for a relocatable type,
35 * the following two sequences of code should be semantically
38 * void move1(T * from, T * to) {
43 * void move2(T * from, T * to) {
44 * memcpy(to, from, sizeof(T));
47 * Most C++ types are relocatable; the ones that aren't would include
48 * internal pointers or (very rarely) would need to update remote
49 * pointers to pointers tracking them. All C++ primitive types and
50 * type constructors are relocatable.
52 * This property can be used in a variety of optimizations. Currently
53 * fbvector uses this property intensively.
55 * The default conservatively assumes the type is not
56 * relocatable. Several specializations are defined for known
57 * types. You may want to add your own specializations. Do so in
58 * namespace folly and make sure you keep the specialization of
59 * IsRelocatable<SomeStruct> in the same header as SomeStruct.
61 template <class T> struct IsRelocatable : boost::mpl::not_<boost::is_class<T> >
67 * Use this macro ONLY inside namespace folly. When using it with a
68 * regular type, use it like this:
70 * // Make sure you're at namespace ::folly scope
71 * template<> FOLLY_ASSUME_RELOCATABLE(MyType)
73 * When using it with a template type, use it like this:
75 * // Make sure you're at namespace ::folly scope
76 * template<class T1, class T2>
77 * FOLLY_ASSUME_RELOCATABLE(MyType<T1, T2>)
79 #define FOLLY_ASSUME_RELOCATABLE(...) \
80 struct IsRelocatable< __VA_ARGS__ > : ::boost::true_type {};
83 * Use this macro ONLY inside namespace boost. When using it with a
84 * regular type, use it like this:
86 * // Make sure you're at namespace ::boost scope
87 * template<> FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyType)
89 * When using it with a template type, use it like this:
91 * // Make sure you're at namespace ::boost scope
92 * template<class T1, class T2>
93 * FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyType<T1, T2>)
95 #define FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(...) \
96 struct has_nothrow_constructor< __VA_ARGS__ > : ::boost::true_type {};
99 * The FOLLY_ASSUME_FBVECTOR_COMPATIBLE* macros below encode two
100 * assumptions: first, that the type is relocatable per IsRelocatable
101 * above, and that it has a nothrow constructor. Most types can be
102 * assumed to satisfy both conditions, but it is the responsibility of
103 * the user to state that assumption. User-defined classes will not
104 * work with fbvector (see FBVector.h) unless they state this
105 * combination of properties.
107 * Use FOLLY_ASSUME_FBVECTOR_COMPATIBLE with regular types like this:
109 * FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MyType)
111 * The versions FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1, _2, _3, and _4
112 * allow using the macro for describing templatized classes with 1, 2,
113 * 3, and 4 template parameters respectively. For template classes
114 * just use the macro with the appropriate number and pass the name of
115 * the template to it. Example:
117 * template <class T1, class T2> class MyType { ... };
119 * // Make sure you're at global scope
120 * FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyType)
123 // Use this macro ONLY at global level (no namespace)
124 #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE(...) \
125 namespace folly { template<> FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__) } \
127 template<> FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__) }
128 // Use this macro ONLY at global level (no namespace)
129 #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(...) \
131 template <class T1> FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1>) } \
133 template <class T1> FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1>) }
134 // Use this macro ONLY at global level (no namespace)
135 #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(...) \
137 template <class T1, class T2> \
138 FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2>) } \
140 template <class T1, class T2> \
141 FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1, T2>) }
142 // Use this macro ONLY at global level (no namespace)
143 #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(...) \
145 template <class T1, class T2, class T3> \
146 FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3>) } \
148 template <class T1, class T2, class T3> \
149 FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1, T2, T3>) }
150 // Use this macro ONLY at global level (no namespace)
151 #define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(...) \
153 template <class T1, class T2, class T3, class T4> \
154 FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3, T4>) } \
156 template <class T1, class T2, class T3, class T4> \
157 FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1, T2, T3, T4>) }
160 * Instantiate FOLLY_ASSUME_FBVECTOR_COMPATIBLE for a few types. It is
161 * safe to assume that pair is compatible if both of its components
162 * are. Furthermore, all STL containers can be assumed to comply,
163 * although that is not guaranteed by the standard.
168 template <class T, class U>
170 #ifndef _GLIBCXX_USE_FB
171 template <class T, class R, class A>
174 template <class T, class R, class A, class S>
177 template <class T, class A>
179 template <class T, class A>
181 template <class T, class A>
183 template <class T, class C, class A>
185 template <class K, class V, class C, class A>
194 template <class T> class shared_ptr;
196 template <class T, class U>
197 struct has_nothrow_constructor< std::pair<T, U> >
198 : ::boost::mpl::and_< has_nothrow_constructor<T>,
199 has_nothrow_constructor<U> > {};
205 // STL commonly-used types
206 template <class T, class U>
207 struct IsRelocatable< std::pair<T, U> >
208 : ::boost::mpl::and_< IsRelocatable<T>, IsRelocatable<U> > {};
210 // Is T one of T1, T2, ..., Tn?
211 template <class T, class... Ts>
213 enum { value = false };
216 template <class T, class T1, class... Ts>
217 struct IsOneOf<T, T1, Ts...> {
218 enum { value = std::is_same<T, T1>::value || IsOneOf<T, Ts...>::value };
223 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string);
224 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::vector);
225 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::list);
226 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque);
227 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(std::map);
228 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::set);
229 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::unique_ptr);
230 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::shared_ptr);
231 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::function);
234 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(boost::shared_ptr);
236 #endif //FOLLY_BASE_TRAITS_H_