]> git.lyx.org Git - lyx.git/blob - boost/boost/mpl/has_xxx.hpp
Update boost to version 1.58
[lyx.git] / boost / boost / mpl / has_xxx.hpp
1
2 #ifndef BOOST_MPL_HAS_XXX_HPP_INCLUDED
3 #define BOOST_MPL_HAS_XXX_HPP_INCLUDED
4
5 // Copyright Aleksey Gurtovoy 2002-2006
6 // Copyright David Abrahams 2002-2003
7 // Copyright Daniel Walker 2007
8 //
9 // Distributed under the Boost Software License, Version 1.0. 
10 // (See accompanying file LICENSE_1_0.txt or copy at 
11 // http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // See http://www.boost.org/libs/mpl for documentation.
14
15 // $Id$
16 // $Date$
17 // $Revision$
18
19 #include <boost/mpl/bool.hpp>
20 #include <boost/mpl/aux_/na_spec.hpp>
21 #include <boost/mpl/aux_/type_wrapper.hpp>
22 #include <boost/mpl/aux_/yes_no.hpp>
23 #include <boost/mpl/aux_/config/gcc.hpp>
24 #include <boost/mpl/aux_/config/has_xxx.hpp>
25 #include <boost/mpl/aux_/config/msvc_typename.hpp>
26 #include <boost/mpl/aux_/config/msvc.hpp>
27 #include <boost/mpl/aux_/config/static_constant.hpp>
28 #include <boost/mpl/aux_/config/workaround.hpp>
29
30 #include <boost/preprocessor/array/elem.hpp>
31 #include <boost/preprocessor/cat.hpp>
32 #include <boost/preprocessor/control/if.hpp>
33 #include <boost/preprocessor/repetition/enum_params.hpp>
34 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
35
36 #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
37 # include <boost/type_traits/is_class.hpp>
38 #endif
39
40 #if !defined(BOOST_MPL_CFG_NO_HAS_XXX)
41
42 #   if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
43
44 // agurt, 11/sep/02: MSVC-specific version (< 7.1), based on a USENET 
45 // newsgroup's posting by John Madsen (comp.lang.c++.moderated, 
46 // 1999-11-12 19:17:06 GMT); the code is _not_ standard-conforming, but 
47 // it works way more reliably than the SFINAE-based implementation
48
49 // Modified dwa 8/Oct/02 to handle reference types.
50
51 #   include <boost/mpl/if.hpp>
52 #   include <boost/mpl/bool.hpp>
53
54 namespace boost { namespace mpl { namespace aux {
55
56 struct has_xxx_tag;
57
58 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
59 template< typename U > struct msvc_incomplete_array
60 {
61     typedef char (&type)[sizeof(U) + 1];
62 };
63 #endif
64
65 template< typename T >
66 struct msvc_is_incomplete
67 {
68     // MSVC is capable of some kinds of SFINAE.  If U is an incomplete
69     // type, it won't pick the second overload
70     static char tester(...);
71
72 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
73     template< typename U >
74     static typename msvc_incomplete_array<U>::type tester(type_wrapper<U>);
75 #else
76     template< typename U >
77     static char (& tester(type_wrapper<U>) )[sizeof(U)+1];
78 #endif 
79     
80     BOOST_STATIC_CONSTANT(bool, value = 
81           sizeof(tester(type_wrapper<T>())) == 1
82         );
83 };
84
85 template<>
86 struct msvc_is_incomplete<int>
87 {
88     BOOST_STATIC_CONSTANT(bool, value = false);
89 };
90
91 }}}
92
93 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, default_) \
94 template< typename T, typename name = ::boost::mpl::aux::has_xxx_tag > \
95 struct BOOST_PP_CAT(trait,_impl) : T \
96 { \
97     static boost::mpl::aux::no_tag \
98     test(void(*)(::boost::mpl::aux::has_xxx_tag)); \
99     \
100     static boost::mpl::aux::yes_tag test(...); \
101     \
102     BOOST_STATIC_CONSTANT(bool, value = \
103           sizeof(test(static_cast<void(*)(name)>(0))) \
104             != sizeof(boost::mpl::aux::no_tag) \
105         ); \
106     typedef boost::mpl::bool_<value> type; \
107 }; \
108 \
109 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
110 struct trait \
111     : boost::mpl::if_c< \
112           boost::mpl::aux::msvc_is_incomplete<T>::value \
113         , boost::mpl::bool_<false> \
114         , BOOST_PP_CAT(trait,_impl)<T> \
115         >::type \
116 { \
117 }; \
118 \
119 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, void) \
120 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, bool) \
121 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, char) \
122 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed char) \
123 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned char) \
124 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed short) \
125 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned short) \
126 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed int) \
127 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned int) \
128 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed long) \
129 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned long) \
130 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, float) \
131 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, double) \
132 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, long double) \
133 /**/
134
135 #   define BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, T) \
136 template<> struct trait<T> \
137 { \
138     BOOST_STATIC_CONSTANT(bool, value = false); \
139     typedef boost::mpl::bool_<false> type; \
140 }; \
141 /**/
142
143 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
144 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
145     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
146     BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, wchar_t) \
147 /**/
148 #else
149 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
150     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
151 /**/
152 #endif
153
154
155 // SFINAE-based implementations below are derived from a USENET newsgroup's 
156 // posting by Rani Sharoni (comp.lang.c++.moderated, 2002-03-17 07:45:09 PST)
157
158 #   elif BOOST_WORKAROUND(BOOST_MSVC, <= 1400) \
159       || (BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1800)) && defined(__CUDACC__)) \
160       || BOOST_WORKAROUND(__IBMCPP__, <= 700)
161
162 // MSVC 7.1 & MSVC 8.0 & VACPP
163
164 // agurt, 15/jun/05: replace overload-based SFINAE implementation with SFINAE
165 // applied to partial specialization to fix some apparently random failures 
166 // (thanks to Daniel Wallin for researching this!)
167
168 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
169 template< typename T > \
170 struct BOOST_PP_CAT(trait, _msvc_sfinae_helper) \
171 { \
172     typedef void type; \
173 };\
174 \
175 template< typename T, typename U = void > \
176 struct BOOST_PP_CAT(trait,_impl_) \
177 { \
178     BOOST_STATIC_CONSTANT(bool, value = false); \
179     typedef boost::mpl::bool_<value> type; \
180 }; \
181 \
182 template< typename T > \
183 struct BOOST_PP_CAT(trait,_impl_)< \
184       T \
185     , typename BOOST_PP_CAT(trait, _msvc_sfinae_helper)< typename T::name >::type \
186     > \
187 { \
188     BOOST_STATIC_CONSTANT(bool, value = true); \
189     typedef boost::mpl::bool_<value> type; \
190 }; \
191 \
192 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
193 struct trait \
194     : BOOST_PP_CAT(trait,_impl_)<T> \
195 { \
196 }; \
197 /**/
198
199 #   elif BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
200
201 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF(trait, trait_tester, name, default_) \
202 template< typename T, bool IS_CLASS > \
203 struct trait_tester \
204 { \
205     BOOST_STATIC_CONSTANT( bool,  value = false ); \
206 }; \
207 template< typename T > \
208 struct trait_tester< T, true > \
209 { \
210     struct trait_tester_impl \
211     { \
212         template < class U > \
213         static int  resolve( boost::mpl::aux::type_wrapper<U> const volatile * \
214                            , boost::mpl::aux::type_wrapper<typename U::name >* = 0 ); \
215         static char resolve( ... ); \
216     }; \
217     typedef boost::mpl::aux::type_wrapper<T> t_; \
218     BOOST_STATIC_CONSTANT( bool, value = ( sizeof( trait_tester_impl::resolve( static_cast< t_ * >(0) ) ) == sizeof(int) ) ); \
219 }; \
220 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
221 struct trait           \
222 {                      \
223     BOOST_STATIC_CONSTANT( bool, value = (trait_tester< T, boost::is_class< T >::value >::value) );     \
224     typedef boost::mpl::bool_< trait< T, fallback_ >::value > type; \
225 };
226
227 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
228     BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF( trait \
229                                          , BOOST_PP_CAT(trait,_tester)      \
230                                          , name       \
231                                          , default_ ) \
232 /**/
233
234 #   else // other SFINAE-capable compilers
235
236 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
237 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
238 struct trait \
239 { \
240     struct gcc_3_2_wknd \
241     { \
242         template< typename U > \
243         static boost::mpl::aux::yes_tag test( \
244               boost::mpl::aux::type_wrapper<U> const volatile* \
245             , boost::mpl::aux::type_wrapper<BOOST_MSVC_TYPENAME U::name>* = 0 \
246             ); \
247     \
248         static boost::mpl::aux::no_tag test(...); \
249     }; \
250     \
251     typedef boost::mpl::aux::type_wrapper<T> t_; \
252     BOOST_STATIC_CONSTANT(bool, value = \
253           sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) \
254             == sizeof(boost::mpl::aux::yes_tag) \
255         ); \
256     typedef boost::mpl::bool_<value> type; \
257 }; \
258 /**/
259
260 #   endif // BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
261
262
263 #else // BOOST_MPL_CFG_NO_HAS_XXX
264
265 // placeholder implementation
266
267 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
268 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
269 struct trait \
270 { \
271     BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
272     typedef fallback_ type; \
273 }; \
274 /**/
275
276 #endif
277
278 #define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
279     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) \
280 /**/
281
282
283 #if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
284
285 // Create a boolean Metafunction to detect a nested template
286 // member. This implementation is based on a USENET newsgroup's
287 // posting by Aleksey Gurtovoy (comp.lang.c++.moderated, 2002-03-19),
288 // Rani Sharoni's USENET posting cited above, the non-template has_xxx
289 // implementations above, and discussion on the Boost mailing list.
290
291 #   if !defined(BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES)
292 #     if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
293 #       define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 1
294 #     else
295 #       define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 0
296 #     endif
297 #   endif
298
299 #   if !defined(BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION)
300 #     if (defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS))
301 #       define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 1
302 #     else
303 #       define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 0
304 #     endif
305 #   endif
306
307 #   if !defined(BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE)
308 #     if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
309 #       define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 1
310 #     else
311 #       define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 0
312 #     endif
313 #   endif
314
315 // NOTE: Many internal implementation macros take a Boost.Preprocessor
316 // array argument called args which is of the following form.
317 //           ( 4, ( trait, name, max_arity, default_ ) )
318
319 #   define BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \
320       BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _introspect) \
321     /**/
322
323 #   define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
324       BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _substitute), n) \
325     /**/
326
327 #   define BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) \
328       BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _test) \
329     /**/
330
331 // Thanks to Guillaume Melquiond for pointing out the need for the
332 // "substitute" template as an argument to the overloaded test
333 // functions to get SFINAE to work for member templates with the
334 // correct name but different number of arguments.
335 #   define BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE(z, n, args) \
336       template< \
337           template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename V) > class V \
338        > \
339       struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) { \
340       }; \
341     /**/
342
343 #   define BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \
344       BOOST_PP_REPEAT( \
345           BOOST_PP_ARRAY_ELEM(2, args) \
346         , BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE \
347         , args \
348       ) \
349     /**/
350
351 #   if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION
352 #     define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
353         template< typename V > \
354         static boost::mpl::aux::no_tag \
355         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \
356       /**/
357 #   else
358 #     define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
359         static boost::mpl::aux::no_tag \
360         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \
361       /**/
362 #   endif
363
364 #   if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES
365 #     define BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT(z, n, args) \
366         template< typename V > \
367         static boost::mpl::aux::yes_tag \
368         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
369             boost::mpl::aux::type_wrapper< V > const volatile* \
370           , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) < \
371                 V::template BOOST_PP_ARRAY_ELEM(1, args) \
372             >* = 0 \
373         ); \
374       /**/
375 #     define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
376         BOOST_PP_REPEAT( \
377             BOOST_PP_ARRAY_ELEM(2, args) \
378           , BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT \
379           , args \
380         ) \
381       /**/
382 #   else
383 #     define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
384         template< typename V > \
385         static boost::mpl::aux::yes_tag \
386         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
387             V const volatile* \
388           , member_macro(args, V, T)* = 0 \
389         ); \
390       /**/
391 #   endif
392
393 #   if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION
394 #     define BOOST_MPL_HAS_MEMBER_TEST(args) \
395           sizeof(BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U >(0)) \
396               == sizeof(boost::mpl::aux::yes_tag) \
397       /**/
398 #   else
399 #     if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES
400 #       define BOOST_MPL_HAS_MEMBER_TEST(args) \
401           sizeof( \
402               BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
403                   static_cast< boost::mpl::aux::type_wrapper< U >* >(0) \
404               ) \
405           ) == sizeof(boost::mpl::aux::yes_tag) \
406         /**/
407 #     else
408 #       define BOOST_MPL_HAS_MEMBER_TEST(args) \
409           sizeof( \
410               BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
411                   static_cast< U* >(0) \
412               ) \
413           ) == sizeof(boost::mpl::aux::yes_tag) \
414         /**/
415 #     endif
416 #   endif
417
418 #   define BOOST_MPL_HAS_MEMBER_INTROSPECT( \
419                args, substitute_macro, member_macro \
420            ) \
421       template< typename U > \
422       struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) { \
423           BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \
424           BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
425           BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
426           BOOST_STATIC_CONSTANT( \
427               bool, value = BOOST_MPL_HAS_MEMBER_TEST(args) \
428           ); \
429           typedef boost::mpl::bool_< value > type; \
430       }; \
431     /**/
432
433 #   define BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
434                args, introspect_macro, substitute_macro, member_macro \
435            ) \
436       template< \
437           typename T \
438         , typename fallback_ \
439               = boost::mpl::bool_< BOOST_PP_ARRAY_ELEM(3, args) > \
440       > \
441       class BOOST_PP_ARRAY_ELEM(0, args) { \
442           introspect_macro(args, substitute_macro, member_macro) \
443       public: \
444           static const bool value \
445               = BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< T >::value; \
446           typedef typename BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< \
447               T \
448           >::type type; \
449       }; \
450     /**/
451
452 // BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE expands to the full
453 // implementation of the function-based metafunction. Compile with -E
454 // to see the preprocessor output for this macro.
455 #   define BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \
456                args, substitute_macro, member_macro \
457            ) \
458       BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
459           args \
460         , BOOST_MPL_HAS_MEMBER_INTROSPECT \
461         , substitute_macro \
462         , member_macro \
463       ) \
464     /**/
465
466 #   if BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE
467
468 #     if !defined(BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE)
469 #       if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
470 #         define BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE 1
471 #       endif
472 #     endif
473
474 #     if !BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE
475 #       define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
476                    args, n \
477                ) \
478           BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
479         /**/
480 #     else
481 #       define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
482                    args, n \
483                ) \
484           BOOST_PP_CAT( \
485               boost_mpl_has_xxx_ \
486             , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
487           ) \
488         /**/
489 #     endif
490
491 #     define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME( \
492                  args \
493              ) \
494         BOOST_PP_CAT( \
495             BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
496                 args, 0 \
497             ) \
498           , _tag \
499         ) \
500       /**/
501
502 #     define BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
503                  z, n, args \
504              ) \
505         template< \
506              template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename U) > class U \
507         > \
508         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
509                 args, n \
510                ) { \
511             typedef \
512                 BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \
513                 type; \
514         }; \
515       /**/
516
517 #     define BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
518                  args, substitute_macro \
519              ) \
520         typedef void \
521             BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args); \
522         BOOST_PP_REPEAT( \
523             BOOST_PP_ARRAY_ELEM(2, args) \
524           , BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE \
525           , args \
526         ) \
527       /**/
528
529 #     define BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE( \
530                  args, member_macro \
531              ) \
532         template< \
533             typename U \
534           , typename V \
535                 = BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \
536         > \
537         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) { \
538             BOOST_STATIC_CONSTANT(bool, value = false); \
539             typedef boost::mpl::bool_< value > type; \
540         }; \
541       /**/
542
543 #     define BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT_WITH_TEMPLATE_SFINAE( \
544                  z, n, args \
545              ) \
546         template< typename U > \
547         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< \
548             U \
549           , typename \
550                 BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
551                     args, n \
552                 )< \
553                     BOOST_MSVC_TYPENAME U::BOOST_PP_ARRAY_ELEM(1, args)< > \
554                 >::type \
555         > { \
556             BOOST_STATIC_CONSTANT(bool, value = true); \
557             typedef boost::mpl::bool_< value > type; \
558         }; \
559       /**/
560
561 #     define BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE( \
562                  args, member_macro \
563              ) \
564         BOOST_PP_REPEAT( \
565             BOOST_PP_ARRAY_ELEM(2, args) \
566           , BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT_WITH_TEMPLATE_SFINAE \
567           , args \
568         ) \
569       /**/
570
571 #     define BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE( \
572                  args, substitute_macro, member_macro \
573              ) \
574         BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE(args, member_macro) \
575         BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE(args, member_macro) \
576         template< typename U > \
577         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \
578             : BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U > { \
579         }; \
580       /**/
581  
582 // BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE expands to the full
583 // implementation of the template-based metafunction. Compile with -E
584 // to see the preprocessor output for this macro.
585 //
586 // Note that if BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE is
587 // defined BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE needs
588 // to be expanded at namespace level before
589 // BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE can be used.
590 #     define BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \
591                  args, substitute_macro, member_macro \
592              ) \
593         BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
594             args, substitute_macro \
595         ) \
596         BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
597             args \
598           , BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE \
599           , substitute_macro \
600           , member_macro \
601         ) \
602       /**/
603
604 #   endif // BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE
605
606 // Note: In the current implementation the parameter and access macros
607 // are no longer expanded.
608 #   if !BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
609 #     define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
610         BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \
611             ( 4, ( trait, name, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, default_ ) ) \
612           , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \
613           , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \
614         ) \
615       /**/
616 #   else
617 #     define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
618         BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \
619             ( 4, ( trait, name, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, default_ ) ) \
620           , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \
621           , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \
622         ) \
623       /**/
624 #   endif
625
626 #else // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
627
628 // placeholder implementation
629
630 #   define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
631       template< typename T \
632               , typename fallback_ = boost::mpl::bool_< default_ > > \
633       struct trait { \
634           BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
635           typedef fallback_ type; \
636       }; \
637     /**/
638
639 #endif // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
640
641 #   define BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name) \
642       BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF( \
643           BOOST_PP_CAT(has_, name), name, false \
644       ) \
645     /**/
646
647 #endif // BOOST_MPL_HAS_XXX_HPP_INCLUDED