1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2006-2014 |
4 | // (C) Copyright Microsoft Corporation 2014 |
5 | // |
6 | // Distributed under the Boost Software License, Version 1.0. |
7 | // (See accompanying file LICENSE_1_0.txt or copy at |
8 | // http://www.boost.org/LICENSE_1_0.txt) |
9 | // |
10 | // See http://www.boost.org/libs/intrusive for documentation. |
11 | // |
12 | ///////////////////////////////////////////////////////////////////////////// |
13 | |
14 | #ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP |
15 | #define BOOST_INTRUSIVE_DETAIL_MPL_HPP |
16 | |
17 | #ifndef BOOST_CONFIG_HPP |
18 | # include <boost/config.hpp> |
19 | #endif |
20 | |
21 | #if defined(BOOST_HAS_PRAGMA_ONCE) |
22 | # pragma once |
23 | #endif |
24 | |
25 | #include <boost/intrusive/detail/config_begin.hpp> |
26 | #include <cstddef> |
27 | |
28 | namespace boost { |
29 | namespace intrusive { |
30 | namespace detail { |
31 | |
32 | template <typename T, typename U> |
33 | struct is_same |
34 | { |
35 | static const bool value = false; |
36 | }; |
37 | |
38 | template <typename T> |
39 | struct is_same<T, T> |
40 | { |
41 | static const bool value = true; |
42 | }; |
43 | |
44 | template<typename T> |
45 | struct add_const |
46 | { typedef const T type; }; |
47 | |
48 | template<typename T> |
49 | struct remove_const |
50 | { typedef T type; }; |
51 | |
52 | template<typename T> |
53 | struct remove_const<const T> |
54 | { typedef T type; }; |
55 | |
56 | template<typename T> |
57 | struct remove_cv |
58 | { typedef T type; }; |
59 | |
60 | template<typename T> |
61 | struct remove_cv<const T> |
62 | { typedef T type; }; |
63 | |
64 | template<typename T> |
65 | struct remove_cv<const volatile T> |
66 | { typedef T type; }; |
67 | |
68 | template<typename T> |
69 | struct remove_cv<volatile T> |
70 | { typedef T type; }; |
71 | |
72 | template<class T> |
73 | struct remove_reference |
74 | { |
75 | typedef T type; |
76 | }; |
77 | |
78 | template<class T> |
79 | struct remove_reference<T&> |
80 | { |
81 | typedef T type; |
82 | }; |
83 | |
84 | template<class T> |
85 | struct remove_pointer |
86 | { |
87 | typedef T type; |
88 | }; |
89 | |
90 | template<class T> |
91 | struct remove_pointer<T*> |
92 | { |
93 | typedef T type; |
94 | }; |
95 | |
96 | template<class T> |
97 | struct add_pointer |
98 | { |
99 | typedef T *type; |
100 | }; |
101 | |
102 | typedef char one; |
103 | struct two {one _[2];}; |
104 | |
105 | template< bool C_ > |
106 | struct bool_ |
107 | { |
108 | static const bool value = C_; |
109 | }; |
110 | |
111 | template< class Integer, Integer Value > |
112 | struct integer |
113 | { |
114 | static const Integer value = Value; |
115 | }; |
116 | |
117 | typedef bool_<true> true_; |
118 | typedef bool_<false> false_; |
119 | |
120 | typedef true_ true_type; |
121 | typedef false_ false_type; |
122 | |
123 | typedef char yes_type; |
124 | struct no_type |
125 | { |
126 | char padding[8]; |
127 | }; |
128 | |
129 | template <bool B, class T = void> |
130 | struct enable_if_c { |
131 | typedef T type; |
132 | }; |
133 | |
134 | template <class T> |
135 | struct enable_if_c<false, T> {}; |
136 | |
137 | template <class Cond, class T = void> |
138 | struct enable_if : public enable_if_c<Cond::value, T>{}; |
139 | |
140 | template<class F, class Param> |
141 | struct apply |
142 | { |
143 | typedef typename F::template apply<Param>::type type; |
144 | }; |
145 | |
146 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) |
147 | |
148 | template <class T, class U> |
149 | struct is_convertible |
150 | { |
151 | static const bool value = __is_convertible_to(T, U); |
152 | }; |
153 | |
154 | #else |
155 | |
156 | template <class T, class U> |
157 | class is_convertible |
158 | { |
159 | typedef char true_t; |
160 | class false_t { char dummy[2]; }; |
161 | //use any_conversion as first parameter since in MSVC |
162 | //overaligned types can't go through ellipsis |
163 | static false_t dispatch(...); |
164 | static true_t dispatch(U); |
165 | static typename remove_reference<T>::type &trigger(); |
166 | public: |
167 | static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); |
168 | }; |
169 | |
170 | #endif |
171 | |
172 | template< |
173 | bool C |
174 | , typename T1 |
175 | , typename T2 |
176 | > |
177 | struct if_c |
178 | { |
179 | typedef T1 type; |
180 | }; |
181 | |
182 | template< |
183 | typename T1 |
184 | , typename T2 |
185 | > |
186 | struct if_c<false,T1,T2> |
187 | { |
188 | typedef T2 type; |
189 | }; |
190 | |
191 | template< |
192 | typename C |
193 | , typename T1 |
194 | , typename T2 |
195 | > |
196 | struct if_ |
197 | { |
198 | typedef typename if_c<0 != C::value, T1, T2>::type type; |
199 | }; |
200 | |
201 | template< |
202 | bool C |
203 | , typename F1 |
204 | , typename F2 |
205 | > |
206 | struct eval_if_c |
207 | : if_c<C,F1,F2>::type |
208 | {}; |
209 | |
210 | template< |
211 | typename C |
212 | , typename T1 |
213 | , typename T2 |
214 | > |
215 | struct eval_if |
216 | : if_<C,T1,T2>::type |
217 | {}; |
218 | |
219 | // identity is an extension: it is not part of the standard. |
220 | template <class T> |
221 | struct identity |
222 | { |
223 | typedef T type; |
224 | }; |
225 | |
226 | template<class T, bool Add> |
227 | struct add_const_if_c |
228 | { |
229 | typedef typename if_c |
230 | < Add |
231 | , typename add_const<T>::type |
232 | , T |
233 | >::type type; |
234 | }; |
235 | |
236 | |
237 | //boost::alignment_of yields to 10K lines of preprocessed code, so we |
238 | //need an alternative |
239 | template <typename T> struct alignment_of; |
240 | |
241 | template <typename T> |
242 | struct alignment_of_hack |
243 | { |
244 | char c; |
245 | T t; |
246 | alignment_of_hack(); |
247 | }; |
248 | |
249 | template <unsigned A, unsigned S> |
250 | struct alignment_logic |
251 | { |
252 | static const std::size_t value = A < S ? A : S; |
253 | }; |
254 | |
255 | template< typename T > |
256 | struct alignment_of |
257 | { |
258 | static const std::size_t value = alignment_logic |
259 | < sizeof(alignment_of_hack<T>) - sizeof(T) |
260 | , sizeof(T) |
261 | >::value; |
262 | }; |
263 | |
264 | template<class Class> |
265 | class is_empty_class |
266 | { |
267 | template <typename T> |
268 | struct empty_helper_t1 : public T |
269 | { |
270 | empty_helper_t1(); |
271 | int i[256]; |
272 | }; |
273 | |
274 | struct empty_helper_t2 |
275 | { int i[256]; }; |
276 | |
277 | public: |
278 | static const bool value = sizeof(empty_helper_t1<Class>) == sizeof(empty_helper_t2); |
279 | }; |
280 | |
281 | template<std::size_t S> |
282 | struct ls_zeros |
283 | { |
284 | static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value); |
285 | }; |
286 | |
287 | template<> |
288 | struct ls_zeros<0> |
289 | { |
290 | static const std::size_t value = 0; |
291 | }; |
292 | |
293 | template<> |
294 | struct ls_zeros<1> |
295 | { |
296 | static const std::size_t value = 0; |
297 | }; |
298 | |
299 | template <typename T> struct unvoid_ref { typedef T &type; }; |
300 | template <> struct unvoid_ref<void> { struct type_impl { }; typedef type_impl & type; }; |
301 | template <> struct unvoid_ref<const void> { struct type_impl { }; typedef type_impl & type; }; |
302 | |
303 | // Infrastructure for providing a default type for T::TNAME if absent. |
304 | #define BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(TNAME) \ |
305 | template <typename T, typename DefaultType> \ |
306 | struct boost_intrusive_default_type_ ## TNAME \ |
307 | { \ |
308 | template <typename X> \ |
309 | static char test(int, typename X::TNAME*); \ |
310 | \ |
311 | template <typename X> \ |
312 | static int test(...); \ |
313 | \ |
314 | struct DefaultWrap { typedef DefaultType TNAME; }; \ |
315 | \ |
316 | static const bool value = (1 == sizeof(test<T>(0, 0))); \ |
317 | \ |
318 | typedef typename \ |
319 | ::boost::intrusive::detail::if_c \ |
320 | <value, T, DefaultWrap>::type::TNAME type; \ |
321 | }; \ |
322 | // |
323 | |
324 | #define BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(INSTANTIATION_NS_PREFIX, T, TNAME, TIMPL) \ |
325 | typename INSTANTIATION_NS_PREFIX \ |
326 | boost_intrusive_default_type_ ## TNAME< T, TIMPL >::type \ |
327 | // |
328 | |
329 | #define BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(TNAME)\ |
330 | template <typename T, typename DefaultType> \ |
331 | struct boost_intrusive_eval_default_type_ ## TNAME \ |
332 | { \ |
333 | template <typename X> \ |
334 | static char test(int, typename X::TNAME*); \ |
335 | \ |
336 | template <typename X> \ |
337 | static int test(...); \ |
338 | \ |
339 | struct DefaultWrap \ |
340 | { typedef typename DefaultType::type TNAME; }; \ |
341 | \ |
342 | static const bool value = (1 == sizeof(test<T>(0, 0))); \ |
343 | \ |
344 | typedef typename \ |
345 | ::boost::intrusive::detail::eval_if_c \ |
346 | < value \ |
347 | , ::boost::intrusive::detail::identity<T> \ |
348 | , ::boost::intrusive::detail::identity<DefaultWrap> \ |
349 | >::type::TNAME type; \ |
350 | }; \ |
351 | // |
352 | |
353 | #define BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(INSTANTIATION_NS_PREFIX, T, TNAME, TIMPL) \ |
354 | typename INSTANTIATION_NS_PREFIX \ |
355 | boost_intrusive_eval_default_type_ ## TNAME< T, TIMPL >::type \ |
356 | // |
357 | |
358 | #define BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(TRAITS_PREFIX, TYPEDEF_TO_FIND) \ |
359 | template <class T>\ |
360 | struct TRAITS_PREFIX##_bool\ |
361 | {\ |
362 | template<bool Add>\ |
363 | struct two_or_three {one _[2 + Add];};\ |
364 | template <class U> static one test(...);\ |
365 | template <class U> static two_or_three<U::TYPEDEF_TO_FIND> test (int);\ |
366 | static const std::size_t value = sizeof(test<T>(0));\ |
367 | };\ |
368 | \ |
369 | template <class T>\ |
370 | struct TRAITS_PREFIX##_bool_is_true\ |
371 | {\ |
372 | static const bool value = TRAITS_PREFIX##_bool<T>::value > sizeof(one)*2;\ |
373 | };\ |
374 | // |
375 | |
376 | #define BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(TRAITS_NAME, FUNC_NAME) \ |
377 | template <typename U, typename Signature> \ |
378 | class TRAITS_NAME \ |
379 | { \ |
380 | private: \ |
381 | template<Signature> struct helper;\ |
382 | template<typename T> \ |
383 | static ::boost::intrusive::detail::yes_type check(helper<&T::FUNC_NAME>*); \ |
384 | template<typename T> static ::boost::intrusive::detail::no_type check(...); \ |
385 | public: \ |
386 | static const bool value = sizeof(check<U>(0)) == sizeof(::boost::intrusive::detail::yes_type); \ |
387 | }; \ |
388 | // |
389 | |
390 | #define BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME, FUNC_NAME) \ |
391 | template <typename Type> \ |
392 | struct TRAITS_NAME \ |
393 | { \ |
394 | struct BaseMixin \ |
395 | { \ |
396 | void FUNC_NAME(); \ |
397 | }; \ |
398 | struct Base : public Type, public BaseMixin { Base(); }; \ |
399 | template <typename T, T t> class Helper{}; \ |
400 | template <typename U> \ |
401 | static ::boost::intrusive::detail::no_type check(U*, Helper<void (BaseMixin::*)(), &U::FUNC_NAME>* = 0); \ |
402 | static ::boost::intrusive::detail::yes_type check(...); \ |
403 | static const bool value = sizeof(::boost::intrusive::detail::yes_type) == sizeof(check((Base*)(0))); \ |
404 | };\ |
405 | // |
406 | |
407 | #define BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(TRAITS_NAME, FUNC_NAME) \ |
408 | BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME##_ignore_signature, FUNC_NAME) \ |
409 | \ |
410 | template <typename Type, class> \ |
411 | struct TRAITS_NAME \ |
412 | : public TRAITS_NAME##_ignore_signature<Type> \ |
413 | {};\ |
414 | // |
415 | |
416 | |
417 | template <typename T> |
418 | inline T* addressof(T& obj) |
419 | { |
420 | return static_cast<T*> |
421 | (static_cast<void*> |
422 | (const_cast<char*> |
423 | (&reinterpret_cast<const char&>(obj)) |
424 | ) |
425 | ); |
426 | } |
427 | |
428 | } //namespace detail |
429 | } //namespace intrusive |
430 | } //namespace boost |
431 | |
432 | #include <boost/intrusive/detail/config_end.hpp> |
433 | |
434 | #endif //BOOST_INTRUSIVE_DETAIL_MPL_HPP |
435 | |