Ticket #9332: has_member_function_callable_with.hpp

File has_member_function_callable_with.hpp, 18.2 KB (added by anonymous, 7 years ago)
Line 
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
25namespace boost_intrusive_hmfcw {
26
27typedef char yes_type;
28struct no_type{ char dummy[2]; };
29
30#if defined(BOOST_NO_CXX11_DECLTYPE)
31
32#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
33
34template<class T>
35struct make_dontcare
36{
37 typedef dont_care type;
38};
39
40#endif
41
42struct dont_care
43{
44 dont_care(...);
45};
46
47struct private_type
48{
49 static private_type p;
50 private_type const &operator,(int) const;
51};
52
53template<typename T>
54no_type is_private_type(T const &);
55yes_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
61template<typename T> struct remove_cv { typedef T type; };
62template<typename T> struct remove_cv<const T> { typedef T type; };
63template<typename T> struct remove_cv<const volatile T> { typedef T type; };
64template<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
102BOOST_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>
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 //add by madengwei
114 struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
115 <Fun, true>
116 {
117 template<class U>
118 static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
119 <U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
120
121 #ifdef BOOST_MSVC
122 template<class U>
123 static decltype( boost::move_detail::declval<Fun>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
124 , boost_intrusive_has_member_function_callable_with::yes_type())
125 Test(Fun*);
126 #else
127 template<class U>
128 static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
129 <U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
130 #endif
131 }
132 template<class U>
133 static boost_intrusive_hmfcw::no_type Test(...);
134 static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(boost_intrusive_hmfcw::yes_type);
135 };
136
137#else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_DECLTYPE)
138
139 /////////////////////////////////////////////////////////
140 /////////////////////////////////////////////////////////
141 //
142 // has_member_function_callable_with_impl_XXX
143 // declaration, special case and 0 arg specializaton
144 //
145 /////////////////////////////////////////////////////////
146 /////////////////////////////////////////////////////////
147
148 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
149 /////////////////////////////////////////////////////////
150 /////////////////////////////////////////////////////////
151 //
152 // has_member_function_callable_with_impl_XXX for 1 to N arguments
153 //
154 /////////////////////////////////////////////////////////
155 /////////////////////////////////////////////////////////
156
157 //defined(BOOST_NO_CXX11_DECLTYPE) must be true
158 template<class Fun, class ...DontCares>
159 struct FunWrapTmpl : Fun
160 {
161 using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
162 boost_intrusive_hmfcw::private_type BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(DontCares...) const;
163 };
164
165 template<typename Fun, class ...Args>
166 struct BOOST_MOVE_CAT(has_member_function_callable_with_,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, Args...>
167 {
168 typedef FunWrapTmpl<typename boost_intrusive_hmfcw::make_dontcare<Args>::type...> FunWrap;
169
170 static bool const value = (sizeof(boost_intrusive_hmfcw::no_type) ==
171 sizeof(boost_intrusive_hmfcw::is_private_type
172 ( (::boost::move_detail::declval< FunWrap<Fun> >().
173 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(::boost::move_detail::declval<Args>()...), 0) )
174 )
175 );
176 };
177 #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
178
179 //Preprocessor must be used to generate specializations instead of variadic templates
180
181 template <typename Type>
182 class BOOST_MOVE_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
183 {
184 struct BaseMixin
185 {
186 void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME();
187 };
188
189 struct Base
190 : public boost_intrusive_hmfcw::remove_cv<Type>::type, public BaseMixin
191 { //Declare the unneeded default constructor as some old compilers wrongly require it with is_convertible
192 Base();
193 };
194 template <typename T, T t> class Helper{};
195
196 template <typename U>
197 static boost_intrusive_hmfcw::no_type deduce
198 (U*, Helper<void (BaseMixin::*)(), &U::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME>* = 0);
199 static boost_intrusive_hmfcw::yes_type deduce(...);
200
201 public:
202 static const bool value = sizeof(boost_intrusive_hmfcw::yes_type) == sizeof(deduce((Base*)0));
203 };
204
205 /////////////////////////////////////////////////////////
206 /////////////////////////////////////////////////////////
207 //
208 // has_member_function_callable_with_impl_XXX specializations
209 //
210 /////////////////////////////////////////////////////////
211
212 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)>
213 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME);
214
215 //No BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME member specialization
216 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)>
217 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
218 <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)>
219 {
220 static const bool value = false;
221 };
222
223 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN == 0
224 //0 arg specialization when BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME is present
225 #if !defined(BOOST_NO_CXX11_DECLTYPE)
226
227 template<typename Fun>
228 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true>
229 {
230 template<class U>
231 static decltype(boost::move_detail::declval<U>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
232 , boost_intrusive_hmfcw::yes_type()) Test(U* f);
233
234 template<class U>
235 static boost_intrusive_hmfcw::no_type Test(...);
236 static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(boost_intrusive_hmfcw::yes_type);
237 };
238
239 #else //defined(BOOST_NO_CXX11_DECLTYPE)
240
241 #if !defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
242
243 template<class F, std::size_t N = sizeof(boost::move_detail::declval<F>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(), 0)>
244 struct BOOST_MOVE_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
245 { boost_intrusive_hmfcw::yes_type dummy[N ? 1 : 2]; };
246
247 template<typename Fun>
248 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true>
249 {
250 template<class U> static BOOST_MOVE_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>
251 Test(BOOST_MOVE_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
252 template<class U> static boost_intrusive_hmfcw::no_type Test(...);
253 static const bool value = sizeof(Test< Fun >(0)) == sizeof(boost_intrusive_hmfcw::yes_type);
254 };
255
256 #else //defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
257
258 template<typename Fun>
259 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true>
260 {//GCC [3.4-4.3) gives ICE when instantiating the 0 arg version so it is not supported.
261 static const bool value = true;
262 };
263
264 #endif//!defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
265 #endif //!defined(BOOST_NO_CXX11_DECLTYPE)
266 #endif //#if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN == 0
267
268 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX > 0
269 //1 to N arg specialization when BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME is present
270 //Declare some unneeded default constructor as some old compilers wrongly require it with is_convertible
271 #if defined(BOOST_NO_CXX11_DECLTYPE)
272 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION(N)\
273 \
274 template<class Fun>\
275 struct BOOST_MOVE_CAT(FunWrap##N, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)\
276 : Fun\
277 {\
278 using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;\
279 BOOST_MOVE_CAT(FunWrap##N, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)();\
280 boost_intrusive_hmfcw::private_type BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME\
281 (BOOST_MOVE_REPEAT##N(boost_intrusive_hmfcw::dont_care)) const;\
282 };\
283 \
284 template<typename Fun, BOOST_MOVE_CLASS##N>\
285 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun, true, BOOST_MOVE_TARG##N>\
286 {\
287 static bool const value = (sizeof(boost_intrusive_hmfcw::no_type) == sizeof(boost_intrusive_hmfcw::is_private_type\
288 ( (::boost::move_detail::declval\
289 < BOOST_MOVE_CAT(FunWrap##N, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun> >().\
290 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(BOOST_MOVE_DECLVAL##N), 0) )\
291 )\
292 );\
293 };\
294 //
295 #else
296 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION(N)\
297 template<typename Fun, BOOST_MOVE_CLASS##N>\
298 struct BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)\
299 <Fun, true, BOOST_MOVE_TARG##N>\
300 {\
301 template<class U>\
302 static decltype(boost::move_detail::declval<U>().\
303 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME(BOOST_MOVE_DECLVAL##N)\
304 , boost_intrusive_hmfcw::yes_type()) Test(U* f);\
305 template<class U>\
306 static boost_intrusive_hmfcw::no_type Test(...);\
307 static const bool value = sizeof(Test<Fun>((Fun*)0)) == sizeof(boost_intrusive_hmfcw::yes_type);\
308 };\
309 //
310 #endif
311 ////////////////////////////////////
312 // Build and invoke BOOST_MOVE_ITERATE_NTOM macrofunction, note that N has to be at least 1
313 ////////////////////////////////////
314 #if BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN == 0
315 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN 1
316 #else
317 #define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN
318 #endif
319 BOOST_MOVE_CAT
320 (BOOST_MOVE_CAT(BOOST_MOVE_CAT(BOOST_MOVE_ITERATE_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN), TO)
321 ,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)
322 (BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION)
323 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATION
324 #undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_ITERATE_MIN
325 ////////////////////////////////////
326 // End of BOOST_MOVE_ITERATE_NTOM
327 ////////////////////////////////////
328 #endif //BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX > 0
329
330 /////////////////////////////////////////////////////////
331 /////////////////////////////////////////////////////////
332 //
333 // has_member_function_callable_with_FUNC
334 //
335 /////////////////////////////////////////////////////////
336 /////////////////////////////////////////////////////////
337
338 //Otherwise use the preprocessor
339 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)>
340 struct BOOST_MOVE_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
341 : public BOOST_MOVE_CAT(has_member_function_callable_with_impl_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
342 <Fun
343 , BOOST_MOVE_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun>::value
344 BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF BOOST_MOVE_CAT(BOOST_MOVE_TARG,BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX)>
345 {};
346 #endif //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
347#endif
348
349BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
350
351//Undef local macros
352#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_COMMA_IF
353
354//Undef user defined macros
355#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
356#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN
357#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX
358#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG
359#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END