1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_CALLABLE_WITH_HPP 12 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_CALLABLE_WITH_HPP 13 14 //Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and 15 //wrong SFINAE for GCC 4.2/4.3 16 #if defined(__GNUC__) && !defined(__clang__) && ((__GNUC__*100 + __GNUC_MINOR__*10) >= 340) && ((__GNUC__*100 + __GNUC_MINOR__*10) <= 430) 17 #define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED 18 #elif defined(BOOST_INTEL) && (BOOST_INTEL < 1200 ) 19 #define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED 20 #endif 21 #include <cstddef> 22 #include <boost/move/utility_core.hpp> 23 #include <boost/move/detail/fwd_macros.hpp> 24 25 namespace boost_intrusive_hmfcw { 26 27 typedef char yes_type; 28 struct no_type{ char dummy[2]; }; 29 30 #if defined(BOOST_NO_CXX11_DECLTYPE) 31 32 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 33 34 template<class T> 35 struct make_dontcare 36 { 37 typedef dont_care type; 38 }; 39 40 #endif 41 42 struct dont_care 43 { 44 dont_care(...); 45 }; 46 47 struct private_type 48 { 49 static private_type p; 50 private_type const &operator,(int) const; 51 }; 52 53 template<typename T> 54 no_type is_private_type(T const &); 55 yes_type is_private_type(private_type const &); 56 57 #endif //#if defined(BOOST_NO_CXX11_DECLTYPE) 58 59 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 60 61 template<typename T> struct remove_cv { typedef T type; }; 62 template<typename T> struct remove_cv<const T> { typedef T type; }; 63 template<typename T> struct remove_cv<const volatile T> { typedef T type; }; 64 template<typename T> struct remove_cv<volatile T> { typedef T type; }; 65 66 #endif 67 68 } //namespace boost_intrusive_hmfcw { 69 70 #endif //BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_CALLABLE_WITH_HPP 71 72 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME 73 #error "You MUST define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME before including this header!" 74 #endif 75 76 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 77 #error "You MUST define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN before including this header!" 78 #endif 79 80 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 81 #error "You MUST define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX before including this header!" 82 #endif 83 84 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX < BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 85 #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX value MUST be greater or equal than BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN!" 86 #endif 87 88 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX == 0 89 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF 90 #else 91 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF , 92 #endif 93 94 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG 95 #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG not defined!" 96 #endif 97 98 #ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END 99 #error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!" 100 #endif 101 102 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG 103 104 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) 105 //With decltype and variadic templaes, things are pretty easy 106 template<typename Fun, class ...Args> BOOST_MOVE_CAT(has_member_function_callable_with_,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)107 struct BOOST_MOVE_CAT(has_member_function_callable_with_,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) 108 { 109 template<class U> 110 static decltype(boost::move_detail::declval<U>(). 111 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(::boost::move_detail::declval<Args>()...) 112 , boost_intrusive_hmfcw::yes_type()) Test(U* f); 113 template<class U> 114 static boost_intrusive_hmfcw::no_type Test(...); 115 static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(boost_intrusive_hmfcw::yes_type); 116 }; 117 118 #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_DECLTYPE) 119 120 ///////////////////////////////////////////////////////// 121 ///////////////////////////////////////////////////////// 122 // 123 // has_member_function_callable_with_impl_XXX 124 // declaration, special case and 0 arg specializaton 125 // 126 ///////////////////////////////////////////////////////// 127 ///////////////////////////////////////////////////////// 128 129 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 130 ///////////////////////////////////////////////////////// 131 ///////////////////////////////////////////////////////// 132 // 133 // has_member_function_callable_with_impl_XXX for 1 to N arguments 134 // 135 ///////////////////////////////////////////////////////// 136 ///////////////////////////////////////////////////////// 137 138 //defined(BOOST_NO_CXX11_DECLTYPE) must be true 139 template<class Fun, class ...DontCares> 140 struct FunWrapTmpl : Fun 141 { 142 using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME; 143 boost_intrusive_hmfcw::private_type BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(DontCares...) const; 144 }; 145 146 template<typename Fun, class ...Args> 147 struct BOOST_MOVE_CAT(has_member_function_callable_with_,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, Args...> 148 { 149 typedef FunWrapTmpl<typename boost_intrusive_hmfcw::make_dontcare<Args>::type...> FunWrap; 150 151 static bool const value = (sizeof(boost_intrusive_hmfcw::no_type) == 152 sizeof(boost_intrusive_hmfcw::is_private_type 153 ( (::boost::move_detail::declval< FunWrap<Fun> >(). 154 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(::boost::move_detail::declval<Args>()...), 0) ) 155 ) 156 ); 157 }; 158 #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 159 160 //Preprocessor must be used to generate specializations instead of variadic templates 161 162 template <typename Type> 163 class BOOST_MOVE_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) 164 { 165 struct BaseMixin 166 { 167 void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(); 168 }; 169 170 struct Base 171 : public boost_intrusive_hmfcw::remove_cv<Type>::type, public BaseMixin 172 { //Declare the unneeded default constructor as some old compilers wrongly require it with is_convertible 173 Base(); 174 }; 175 template <typename T, T t> class Helper{}; 176 177 template <typename U> 178 static boost_intrusive_hmfcw::no_type deduce 179 (U*, Helper<void (BaseMixin::*)(), &U::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME>* = 0); 180 static boost_intrusive_hmfcw::yes_type deduce(...); 181 182 public: 183 static const bool value = sizeof(boost_intrusive_hmfcw::yes_type) == sizeof(deduce((Base*)0)); 184 }; 185 186 ///////////////////////////////////////////////////////// 187 ///////////////////////////////////////////////////////// 188 // 189 // has_member_function_callable_with_impl_XXX specializations 190 // 191 ///////////////////////////////////////////////////////// 192 193 template<typename Fun, bool HasFunc BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF BOOST_MOVE_CAT(BOOST_MOVE_CLASSDFLT,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)> 194 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME); 195 196 //No BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME member specialization 197 template<typename Fun BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF BOOST_MOVE_CAT(BOOST_MOVE_CLASS,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)> 198 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) 199 <Fun, false BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF BOOST_MOVE_CAT(BOOST_MOVE_TARG,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)> 200 { 201 static const bool value = false; 202 }; 203 204 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN == 0 205 //0 arg specialization when BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME is present 206 #if !defined(BOOST_NO_CXX11_DECLTYPE) 207 208 template<typename Fun> 209 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true> 210 { 211 template<class U> 212 static decltype(boost::move_detail::declval<U>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME() 213 , boost_intrusive_hmfcw::yes_type()) Test(U* f); 214 215 template<class U> 216 static boost_intrusive_hmfcw::no_type Test(...); 217 static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(boost_intrusive_hmfcw::yes_type); 218 }; 219 220 #else //defined(BOOST_NO_CXX11_DECLTYPE) 221 222 #if !defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED) 223 224 template<class F, std::size_t N = sizeof(boost::move_detail::declval<F>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(), 0)> 225 struct BOOST_MOVE_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) 226 { boost_intrusive_hmfcw::yes_type dummy[N ? 1 : 2]; }; 227 228 template<typename Fun> 229 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true> 230 { 231 template<class U> static BOOST_MOVE_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U> 232 Test(BOOST_MOVE_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*); 233 template<class U> static boost_intrusive_hmfcw::no_type Test(...); 234 static const bool value = sizeof(Test< Fun >(0)) == sizeof(boost_intrusive_hmfcw::yes_type); 235 }; 236 237 #else //defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED) 238 239 template<typename Fun> 240 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true> 241 {//GCC [3.4-4.3) gives ICE when instantiating the 0 arg version so it is not supported. 242 static const bool value = true; 243 }; 244 245 #endif//!defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED) 246 #endif //!defined(BOOST_NO_CXX11_DECLTYPE) 247 #endif //#if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN == 0 248 249 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX > 0 250 //1 to N arg specialization when BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME is present 251 //Declare some unneeded default constructor as some old compilers wrongly require it with is_convertible 252 #if defined(BOOST_NO_CXX11_DECLTYPE) 253 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION(N)\ 254 \ 255 template<class Fun>\ 256 struct BOOST_MOVE_CAT(FunWrap##N, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)\ 257 : Fun\ 258 {\ 259 using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;\ 260 BOOST_MOVE_CAT(FunWrap##N, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)();\ 261 boost_intrusive_hmfcw::private_type BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME\ 262 (BOOST_MOVE_REPEAT##N(boost_intrusive_hmfcw::dont_care)) const;\ 263 };\ 264 \ 265 template<typename Fun, BOOST_MOVE_CLASS##N>\ 266 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true, BOOST_MOVE_TARG##N>\ 267 {\ 268 static bool const value = (sizeof(boost_intrusive_hmfcw::no_type) == sizeof(boost_intrusive_hmfcw::is_private_type\ 269 ( (::boost::move_detail::declval\ 270 < BOOST_MOVE_CAT(FunWrap##N, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun> >().\ 271 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(BOOST_MOVE_DECLVAL##N), 0) )\ 272 )\ 273 );\ 274 };\ 275 // 276 #else 277 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION(N)\ 278 template<typename Fun, BOOST_MOVE_CLASS##N>\ 279 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)\ 280 <Fun, true, BOOST_MOVE_TARG##N>\ 281 {\ 282 template<class U>\ 283 static decltype(boost::move_detail::declval<U>().\ 284 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(BOOST_MOVE_DECLVAL##N)\ 285 , boost_intrusive_hmfcw::yes_type()) Test(U* f);\ 286 template<class U>\ 287 static boost_intrusive_hmfcw::no_type Test(...);\ 288 static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(boost_intrusive_hmfcw::yes_type);\ 289 };\ 290 // 291 #endif 292 //////////////////////////////////// 293 // Build and invoke BOOST_MOVE_ITERATE_NTOM macrofunction, note that N has to be at least 1 294 //////////////////////////////////// 295 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN == 0 296 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN 1 297 #else 298 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 299 #endif 300 BOOST_MOVE_CAT 301 (BOOST_MOVE_CAT(BOOST_MOVE_CAT(BOOST_MOVE_ITERATE_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN), TO) 302 ,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX) 303 (BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION) 304 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION 305 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN 306 //////////////////////////////////// 307 // End of BOOST_MOVE_ITERATE_NTOM 308 //////////////////////////////////// 309 #endif //BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX > 0 310 311 ///////////////////////////////////////////////////////// 312 ///////////////////////////////////////////////////////// 313 // 314 // has_member_function_callable_with_FUNC 315 // 316 ///////////////////////////////////////////////////////// 317 ///////////////////////////////////////////////////////// 318 319 //Otherwise use the preprocessor 320 template<typename Fun BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF BOOST_MOVE_CAT(BOOST_MOVE_CLASSDFLT,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)> 321 struct BOOST_MOVE_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) 322 : public BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME) 323 <Fun 324 , BOOST_MOVE_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun>::value 325 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF BOOST_MOVE_CAT(BOOST_MOVE_TARG,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)> 326 {}; 327 #endif //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) 328 #endif 329 330 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END 331 332 //Undef local macros 333 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF 334 335 //Undef user defined macros 336 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME 337 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 338 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 339 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG 340 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END 341