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