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
28namespace boost {
29namespace intrusive {
30namespace detail {
31
32template <typename T, typename U>
33struct is_same
34{
35 static const bool value = false;
36};
37
38template <typename T>
39struct is_same<T, T>
40{
41 static const bool value = true;
42};
43
44template<typename T>
45struct add_const
46{ typedef const T type; };
47
48template<typename T>
49struct remove_const
50{ typedef T type; };
51
52template<typename T>
53struct remove_const<const T>
54{ typedef T type; };
55
56template<typename T>
57struct remove_cv
58{ typedef T type; };
59
60template<typename T>
61struct remove_cv<const T>
62{ typedef T type; };
63
64template<typename T>
65struct remove_cv<const volatile T>
66{ typedef T type; };
67
68template<typename T>
69struct remove_cv<volatile T>
70{ typedef T type; };
71
72template<class T>
73struct remove_reference
74{
75 typedef T type;
76};
77
78template<class T>
79struct remove_reference<T&>
80{
81 typedef T type;
82};
83
84template<class T>
85struct remove_pointer
86{
87 typedef T type;
88};
89
90template<class T>
91struct remove_pointer<T*>
92{
93 typedef T type;
94};
95
96template<class T>
97struct add_pointer
98{
99 typedef T *type;
100};
101
102typedef char one;
103struct two {one _[2];};
104
105template< bool C_ >
106struct bool_
107{
108 static const bool value = C_;
109};
110
111template< class Integer, Integer Value >
112struct integer
113{
114 static const Integer value = Value;
115};
116
117typedef bool_<true> true_;
118typedef bool_<false> false_;
119
120typedef true_ true_type;
121typedef false_ false_type;
122
123typedef char yes_type;
124struct no_type
125{
126 char padding[8];
127};
128
129template <bool B, class T = void>
130struct enable_if_c {
131 typedef T type;
132};
133
134template <class T>
135struct enable_if_c<false, T> {};
136
137template <class Cond, class T = void>
138struct enable_if : public enable_if_c<Cond::value, T>{};
139
140template<class F, class Param>
141struct apply
142{
143 typedef typename F::template apply<Param>::type type;
144};
145
146#if defined(_MSC_VER) && (_MSC_VER >= 1400)
147
148template <class T, class U>
149struct is_convertible
150{
151 static const bool value = __is_convertible_to(T, U);
152};
153
154#else
155
156template <class T, class U>
157class 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
172template<
173 bool C
174 , typename T1
175 , typename T2
176 >
177struct if_c
178{
179 typedef T1 type;
180};
181
182template<
183 typename T1
184 , typename T2
185 >
186struct if_c<false,T1,T2>
187{
188 typedef T2 type;
189};
190
191template<
192 typename C
193 , typename T1
194 , typename T2
195 >
196struct if_
197{
198 typedef typename if_c<0 != C::value, T1, T2>::type type;
199};
200
201template<
202 bool C
203 , typename F1
204 , typename F2
205 >
206struct eval_if_c
207 : if_c<C,F1,F2>::type
208{};
209
210template<
211 typename C
212 , typename T1
213 , typename T2
214 >
215struct eval_if
216 : if_<C,T1,T2>::type
217{};
218
219// identity is an extension: it is not part of the standard.
220template <class T>
221struct identity
222{
223 typedef T type;
224};
225
226template<class T, bool Add>
227struct 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
239template <typename T> struct alignment_of;
240
241template <typename T>
242struct alignment_of_hack
243{
244 char c;
245 T t;
246 alignment_of_hack();
247};
248
249template <unsigned A, unsigned S>
250struct alignment_logic
251{
252 static const std::size_t value = A < S ? A : S;
253};
254
255template< typename T >
256struct 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
264template<class Class>
265class 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
281template<std::size_t S>
282struct ls_zeros
283{
284 static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value);
285};
286
287template<>
288struct ls_zeros<0>
289{
290 static const std::size_t value = 0;
291};
292
293template<>
294struct ls_zeros<1>
295{
296 static const std::size_t value = 0;
297};
298
299template <typename T> struct unvoid_ref { typedef T &type; };
300template <> struct unvoid_ref<void> { struct type_impl { }; typedef type_impl & type; };
301template <> 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) \
359template <class T>\
360struct 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\
369template <class T>\
370struct 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) \
391template <typename Type> \
392struct 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) \
408BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME##_ignore_signature, FUNC_NAME) \
409\
410template <typename Type, class> \
411struct TRAITS_NAME \
412 : public TRAITS_NAME##_ignore_signature<Type> \
413{};\
414//
415
416
417template <typename T>
418inline 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