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