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 <boost/move/detail/type_traits.hpp>
27 #include <cstddef>
28 
29 namespace boost {
30 namespace intrusive {
31 namespace detail {
32 
33 using boost::move_detail::is_same;
34 using boost::move_detail::add_const;
35 using boost::move_detail::remove_const;
36 using boost::move_detail::remove_cv;
37 using boost::move_detail::remove_reference;
38 using boost::move_detail::add_reference;
39 using boost::move_detail::remove_pointer;
40 using boost::move_detail::add_pointer;
41 using boost::move_detail::true_type;
42 using boost::move_detail::false_type;
43 using boost::move_detail::voider;
44 using boost::move_detail::enable_if_c;
45 using boost::move_detail::enable_if;
46 using boost::move_detail::disable_if_c;
47 using boost::move_detail::disable_if;
48 using boost::move_detail::is_convertible;
49 using boost::move_detail::if_c;
50 using boost::move_detail::if_;
51 using boost::move_detail::is_const;
52 using boost::move_detail::identity;
53 using boost::move_detail::alignment_of;
54 using boost::move_detail::is_empty;
55 using boost::move_detail::addressof;
56 using boost::move_detail::integral_constant;
57 using boost::move_detail::enable_if_convertible;
58 using boost::move_detail::disable_if_convertible;
59 using boost::move_detail::bool_;
60 using boost::move_detail::true_;
61 using boost::move_detail::false_;
62 using boost::move_detail::yes_type;
63 using boost::move_detail::no_type;
64 using boost::move_detail::apply;
65 using boost::move_detail::eval_if_c;
66 using boost::move_detail::eval_if;
67 using boost::move_detail::unvoid_ref;
68 using boost::move_detail::add_const_if_c;
69 
70 template<std::size_t S>
71 struct ls_zeros
72 {
73    static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value);
74 };
75 
76 template<>
77 struct ls_zeros<0>
78 {
79    static const std::size_t value = 0;
80 };
81 
82 template<>
83 struct ls_zeros<1>
84 {
85    static const std::size_t value = 0;
86 };
87 
88 // Infrastructure for providing a default type for T::TNAME if absent.
89 #define BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(TNAME)     \
90    template <typename T>                                          \
91    struct boost_intrusive_has_type_ ## TNAME                      \
92    {                                                              \
93       template <typename X>                                       \
94       static char test(int, typename X::TNAME*);                  \
95                                                                   \
96       template <typename X>                                       \
97       static int test(...);                                       \
98                                                                   \
99       static const bool value = (1 == sizeof(test<T>(0, 0)));     \
100    };                                                             \
101                                                                   \
102    template <typename T, typename DefaultType>                    \
103    struct boost_intrusive_default_type_ ## TNAME                  \
104    {                                                              \
105       struct DefaultWrap { typedef DefaultType TNAME; };          \
106                                                                   \
107       typedef typename                                            \
108          ::boost::intrusive::detail::if_c                         \
109             < boost_intrusive_has_type_ ## TNAME<T>::value        \
110             , T, DefaultWrap>::type::TNAME type;                  \
111    };                                                             \
112    //
113 
114 #define BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(INSTANTIATION_NS_PREFIX, T, TNAME, TIMPL)   \
115       typename INSTANTIATION_NS_PREFIX                                                       \
116          boost_intrusive_default_type_ ## TNAME< T, TIMPL >::type                            \
117 //
118 
119 #define BOOST_INTRUSIVE_HAS_TYPE(INSTANTIATION_NS_PREFIX, T, TNAME)  \
120       INSTANTIATION_NS_PREFIX                                        \
121          boost_intrusive_has_type_ ## TNAME< T >::value              \
122 //
123 
124 #define BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(TNAME)\
125    template <typename T, typename DefaultType>                    \
126    struct boost_intrusive_eval_default_type_ ## TNAME             \
127    {                                                              \
128       template <typename X>                                       \
129       static char test(int, typename X::TNAME*);                  \
130                                                                   \
131       template <typename X>                                       \
132       static int test(...);                                       \
133                                                                   \
134       struct DefaultWrap                                          \
135       { typedef typename DefaultType::type TNAME; };              \
136                                                                   \
137       static const bool value = (1 == sizeof(test<T>(0, 0)));     \
138                                                                   \
139       typedef typename                                            \
140          ::boost::intrusive::detail::eval_if_c                    \
141             < value                                               \
142             , ::boost::intrusive::detail::identity<T>             \
143             , ::boost::intrusive::detail::identity<DefaultWrap>   \
144             >::type::TNAME type;                                  \
145    };                                                             \
146 //
147 
148 #define BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(INSTANTIATION_NS_PREFIX, T, TNAME, TIMPL) \
149       typename INSTANTIATION_NS_PREFIX                                                          \
150          boost_intrusive_eval_default_type_ ## TNAME< T, TIMPL >::type                          \
151 //
152 
153 #define BOOST_INTRUSIVE_INTERNAL_STATIC_BOOL_IS_TRUE(TRAITS_PREFIX, TYPEDEF_TO_FIND) \
154 template <class T>\
155 struct TRAITS_PREFIX##_bool\
156 {\
157    template<bool Add>\
158    struct two_or_three {yes_type _[2 + Add];};\
159    template <class U> static yes_type test(...);\
160    template <class U> static two_or_three<U::TYPEDEF_TO_FIND> test (int);\
161    static const std::size_t value = sizeof(test<T>(0));\
162 };\
163 \
164 template <class T>\
165 struct TRAITS_PREFIX##_bool_is_true\
166 {\
167    static const bool value = TRAITS_PREFIX##_bool<T>::value > sizeof(yes_type)*2;\
168 };\
169 //
170 
171 #define BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(TRAITS_NAME, FUNC_NAME) \
172   template <typename U, typename Signature> \
173   class TRAITS_NAME \
174   { \
175   private: \
176   template<Signature> struct helper;\
177   template<typename T> \
178   static ::boost::intrusive::detail::yes_type test(helper<&T::FUNC_NAME>*); \
179   template<typename T> static ::boost::intrusive::detail::no_type test(...); \
180   public: \
181   static const bool value = sizeof(test<U>(0)) == sizeof(::boost::intrusive::detail::yes_type); \
182   }; \
183 //
184 
185 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME, FUNC_NAME) \
186 template <typename Type> \
187 struct TRAITS_NAME \
188 { \
189    struct BaseMixin \
190    { \
191       void FUNC_NAME(); \
192    }; \
193    struct Base : public Type, public BaseMixin { Base(); }; \
194    template <typename T, T t> class Helper{}; \
195    template <typename U> \
196    static ::boost::intrusive::detail::no_type  test(U*, Helper<void (BaseMixin::*)(), &U::FUNC_NAME>* = 0); \
197    static ::boost::intrusive::detail::yes_type test(...); \
198    static const bool value = sizeof(::boost::intrusive::detail::yes_type) == sizeof(test((Base*)(0))); \
199 };\
200 //
201 
202 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(TRAITS_NAME, FUNC_NAME) \
203 BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(TRAITS_NAME##_ignore_signature, FUNC_NAME) \
204 \
205 template <typename Type, class> \
206 struct TRAITS_NAME \
207    : public TRAITS_NAME##_ignore_signature<Type> \
208 {};\
209 //
210 
211 } //namespace detail
212 } //namespace intrusive
213 } //namespace boost
214 
215 #include <boost/intrusive/detail/config_end.hpp>
216 
217 #endif //BOOST_INTRUSIVE_DETAIL_MPL_HPP
218