Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 09:57:29

0001 
0002 #ifndef BOOST_MPL_HAS_XXX_HPP_INCLUDED
0003 #define BOOST_MPL_HAS_XXX_HPP_INCLUDED
0004 
0005 // Copyright Aleksey Gurtovoy 2002-2006
0006 // Copyright David Abrahams 2002-2003
0007 // Copyright Daniel Walker 2007
0008 //
0009 // Distributed under the Boost Software License, Version 1.0. 
0010 // (See accompanying file LICENSE_1_0.txt or copy at 
0011 // http://www.boost.org/LICENSE_1_0.txt)
0012 //
0013 // See http://www.boost.org/libs/mpl for documentation.
0014 
0015 // $Id$
0016 // $Date$
0017 // $Revision$
0018 
0019 #include <boost/mpl/bool.hpp>
0020 #include <boost/mpl/aux_/na_spec.hpp>
0021 #include <boost/mpl/aux_/type_wrapper.hpp>
0022 #include <boost/mpl/aux_/yes_no.hpp>
0023 #include <boost/mpl/aux_/config/gcc.hpp>
0024 #include <boost/mpl/aux_/config/has_xxx.hpp>
0025 #include <boost/mpl/aux_/config/msvc_typename.hpp>
0026 #include <boost/mpl/aux_/config/msvc.hpp>
0027 #include <boost/mpl/aux_/config/static_constant.hpp>
0028 #include <boost/mpl/aux_/config/workaround.hpp>
0029 
0030 #include <boost/preprocessor/array/elem.hpp>
0031 #include <boost/preprocessor/cat.hpp>
0032 #include <boost/preprocessor/control/if.hpp>
0033 #include <boost/preprocessor/repetition/enum_params.hpp>
0034 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0035 
0036 #if BOOST_WORKAROUND( BOOST_BORLANDC, BOOST_TESTED_AT(0x590) )
0037 # include <boost/type_traits/is_class.hpp>
0038 #endif
0039 
0040 #if !defined(BOOST_MPL_CFG_NO_HAS_XXX)
0041 
0042 #   if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
0043 
0044 // agurt, 11/sep/02: MSVC-specific version (< 7.1), based on a USENET 
0045 // newsgroup's posting by John Madsen (comp.lang.c++.moderated, 
0046 // 1999-11-12 19:17:06 GMT); the code is _not_ standard-conforming, but 
0047 // it works way more reliably than the SFINAE-based implementation
0048 
0049 // Modified dwa 8/Oct/02 to handle reference types.
0050 
0051 #   include <boost/mpl/if.hpp>
0052 #   include <boost/mpl/bool.hpp>
0053 
0054 namespace boost { namespace mpl { namespace aux {
0055 
0056 struct has_xxx_tag;
0057 
0058 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
0059 template< typename U > struct msvc_incomplete_array
0060 {
0061     typedef char (&type)[sizeof(U) + 1];
0062 };
0063 #endif
0064 
0065 template< typename T >
0066 struct msvc_is_incomplete
0067 {
0068     // MSVC is capable of some kinds of SFINAE.  If U is an incomplete
0069     // type, it won't pick the second overload
0070     static char tester(...);
0071 
0072 #if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
0073     template< typename U >
0074     static typename msvc_incomplete_array<U>::type tester(type_wrapper<U>);
0075 #else
0076     template< typename U >
0077     static char (& tester(type_wrapper<U>) )[sizeof(U)+1];
0078 #endif 
0079     
0080     BOOST_STATIC_CONSTANT(bool, value = 
0081           sizeof(tester(type_wrapper<T>())) == 1
0082         );
0083 };
0084 
0085 template<>
0086 struct msvc_is_incomplete<int>
0087 {
0088     BOOST_STATIC_CONSTANT(bool, value = false);
0089 };
0090 
0091 }}}
0092 
0093 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, default_) \
0094 template< typename T, typename name = ::boost::mpl::aux::has_xxx_tag > \
0095 struct BOOST_PP_CAT(trait,_impl) : T \
0096 { \
0097     static boost::mpl::aux::no_tag \
0098     test(void(*)(::boost::mpl::aux::has_xxx_tag)); \
0099     \
0100     static boost::mpl::aux::yes_tag test(...); \
0101     \
0102     BOOST_STATIC_CONSTANT(bool, value = \
0103           sizeof(test(static_cast<void(*)(name)>(0))) \
0104             != sizeof(boost::mpl::aux::no_tag) \
0105         ); \
0106     typedef boost::mpl::bool_<value> type; \
0107 }; \
0108 \
0109 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
0110 struct trait \
0111     : boost::mpl::if_c< \
0112           boost::mpl::aux::msvc_is_incomplete<T>::value \
0113         , boost::mpl::bool_<false> \
0114         , BOOST_PP_CAT(trait,_impl)<T> \
0115         >::type \
0116 { \
0117 }; \
0118 \
0119 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, void) \
0120 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, bool) \
0121 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, char) \
0122 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed char) \
0123 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned char) \
0124 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed short) \
0125 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned short) \
0126 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed int) \
0127 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned int) \
0128 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed long) \
0129 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned long) \
0130 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, float) \
0131 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, double) \
0132 BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, long double) \
0133 /**/
0134 
0135 #   define BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, T) \
0136 template<> struct trait<T> \
0137 { \
0138     BOOST_STATIC_CONSTANT(bool, value = false); \
0139     typedef boost::mpl::bool_<false> type; \
0140 }; \
0141 /**/
0142 
0143 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
0144 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
0145     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
0146     BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, wchar_t) \
0147 /**/
0148 #else
0149 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
0150     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
0151 /**/
0152 #endif
0153 
0154 
0155 // SFINAE-based implementations below are derived from a USENET newsgroup's 
0156 // posting by Rani Sharoni (comp.lang.c++.moderated, 2002-03-17 07:45:09 PST)
0157 
0158 #   elif BOOST_WORKAROUND(BOOST_MSVC, <= 1400) \
0159       || (BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1800)) && defined(__CUDACC__)) \
0160       || BOOST_WORKAROUND(__IBMCPP__, <= 700)
0161 
0162 // MSVC 7.1 & MSVC 8.0 & VACPP
0163 
0164 // agurt, 15/jun/05: replace overload-based SFINAE implementation with SFINAE
0165 // applied to partial specialization to fix some apparently random failures 
0166 // (thanks to Daniel Wallin for researching this!)
0167 
0168 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
0169 template< typename T > \
0170 struct BOOST_PP_CAT(trait, _msvc_sfinae_helper) \
0171 { \
0172     typedef void type; \
0173 };\
0174 \
0175 template< typename T, typename U = void > \
0176 struct BOOST_PP_CAT(trait,_impl_) \
0177 { \
0178     BOOST_STATIC_CONSTANT(bool, value = false); \
0179     typedef boost::mpl::bool_<value> type; \
0180 }; \
0181 \
0182 template< typename T > \
0183 struct BOOST_PP_CAT(trait,_impl_)< \
0184       T \
0185     , typename BOOST_PP_CAT(trait, _msvc_sfinae_helper)< typename T::name >::type \
0186     > \
0187 { \
0188     BOOST_STATIC_CONSTANT(bool, value = true); \
0189     typedef boost::mpl::bool_<value> type; \
0190 }; \
0191 \
0192 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
0193 struct trait \
0194     : BOOST_PP_CAT(trait,_impl_)<T> \
0195 { \
0196 }; \
0197 /**/
0198 
0199 #   elif BOOST_WORKAROUND( BOOST_BORLANDC, BOOST_TESTED_AT(0x590) )
0200 
0201 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF(trait, trait_tester, name, default_) \
0202 template< typename T, bool IS_CLASS > \
0203 struct trait_tester \
0204 { \
0205     BOOST_STATIC_CONSTANT( bool,  value = false ); \
0206 }; \
0207 template< typename T > \
0208 struct trait_tester< T, true > \
0209 { \
0210     struct trait_tester_impl \
0211     { \
0212         template < class U > \
0213         static int  resolve( boost::mpl::aux::type_wrapper<U> const volatile * \
0214                            , boost::mpl::aux::type_wrapper<typename U::name >* = 0 ); \
0215         static char resolve( ... ); \
0216     }; \
0217     typedef boost::mpl::aux::type_wrapper<T> t_; \
0218     BOOST_STATIC_CONSTANT( bool, value = ( sizeof( trait_tester_impl::resolve( static_cast< t_ * >(0) ) ) == sizeof(int) ) ); \
0219 }; \
0220 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
0221 struct trait           \
0222 {                      \
0223     BOOST_STATIC_CONSTANT( bool, value = (trait_tester< T, boost::is_class< T >::value >::value) );     \
0224     typedef boost::mpl::bool_< trait< T, fallback_ >::value > type; \
0225 };
0226 
0227 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
0228     BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF( trait \
0229                                          , BOOST_PP_CAT(trait,_tester)      \
0230                                          , name       \
0231                                          , default_ ) \
0232 /**/
0233 
0234 #   else // other SFINAE-capable compilers
0235 
0236 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
0237 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
0238 struct trait \
0239 { \
0240     struct gcc_3_2_wknd \
0241     { \
0242         template< typename U > \
0243         static boost::mpl::aux::yes_tag test( \
0244               boost::mpl::aux::type_wrapper<U> const volatile* \
0245             , boost::mpl::aux::type_wrapper<BOOST_MSVC_TYPENAME U::name>* = 0 \
0246             ); \
0247     \
0248         static boost::mpl::aux::no_tag test(...); \
0249     }; \
0250     \
0251     typedef boost::mpl::aux::type_wrapper<T> t_; \
0252     BOOST_STATIC_CONSTANT(bool, value = \
0253           sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) \
0254             == sizeof(boost::mpl::aux::yes_tag) \
0255         ); \
0256     typedef boost::mpl::bool_<value> type; \
0257 }; \
0258 /**/
0259 
0260 #   endif // BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
0261 
0262 
0263 #else // BOOST_MPL_CFG_NO_HAS_XXX
0264 
0265 // placeholder implementation
0266 
0267 #   define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
0268 template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
0269 struct trait \
0270 { \
0271     BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
0272     typedef fallback_ type; \
0273 }; \
0274 /**/
0275 
0276 #endif
0277 
0278 #define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
0279     BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) \
0280 /**/
0281 
0282 
0283 #if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
0284 
0285 // Create a boolean Metafunction to detect a nested template
0286 // member. This implementation is based on a USENET newsgroup's
0287 // posting by Aleksey Gurtovoy (comp.lang.c++.moderated, 2002-03-19),
0288 // Rani Sharoni's USENET posting cited above, the non-template has_xxx
0289 // implementations above, and discussion on the Boost mailing list.
0290 
0291 #   if !defined(BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES)
0292 #     if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
0293 #       define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 1
0294 #     else
0295 #       define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 0
0296 #     endif
0297 #   endif
0298 
0299 #   if !defined(BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION)
0300 #     if (defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS))
0301 #       define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 1
0302 #     else
0303 #       define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 0
0304 #     endif
0305 #   endif
0306 
0307 #   if !defined(BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE)
0308 #     if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
0309 #       define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 1
0310 #     else
0311 #       define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 0
0312 #     endif
0313 #   endif
0314 
0315 // NOTE: Many internal implementation macros take a Boost.Preprocessor
0316 // array argument called args which is of the following form.
0317 //           ( 4, ( trait, name, max_arity, default_ ) )
0318 
0319 #   define BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \
0320       BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _introspect) \
0321     /**/
0322 
0323 #   define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
0324       BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _substitute), n) \
0325     /**/
0326 
0327 #   define BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) \
0328       BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _test) \
0329     /**/
0330 
0331 // Thanks to Guillaume Melquiond for pointing out the need for the
0332 // "substitute" template as an argument to the overloaded test
0333 // functions to get SFINAE to work for member templates with the
0334 // correct name but different number of arguments.
0335 #   define BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE(z, n, args) \
0336       template< \
0337           template< BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), typename V) > class V \
0338        > \
0339       struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) { \
0340       }; \
0341     /**/
0342 
0343 #   define BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \
0344       BOOST_PP_REPEAT( \
0345           BOOST_PP_ARRAY_ELEM(2, args) \
0346         , BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE \
0347         , args \
0348       ) \
0349     /**/
0350 
0351 #   if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION
0352 #     define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
0353         template< typename V > \
0354         static boost::mpl::aux::no_tag \
0355         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \
0356       /**/
0357 #   else
0358 #     define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
0359         static boost::mpl::aux::no_tag \
0360         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \
0361       /**/
0362 #   endif
0363 
0364 #   if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES
0365 #     define BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT(z, n, args) \
0366         template< typename V > \
0367         static boost::mpl::aux::yes_tag \
0368         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
0369             boost::mpl::aux::type_wrapper< V > const volatile* \
0370           , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) < \
0371                 V::template BOOST_PP_ARRAY_ELEM(1, args) \
0372             >* = 0 \
0373         ); \
0374       /**/
0375 #     define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
0376         BOOST_PP_REPEAT( \
0377             BOOST_PP_ARRAY_ELEM(2, args) \
0378           , BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT \
0379           , args \
0380         ) \
0381       /**/
0382 #   else
0383 #     define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
0384         template< typename V > \
0385         static boost::mpl::aux::yes_tag \
0386         BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
0387             V const volatile* \
0388           , member_macro(args, V, T)* = 0 \
0389         ); \
0390       /**/
0391 #   endif
0392 
0393 #   if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION
0394 #     define BOOST_MPL_HAS_MEMBER_TEST(args) \
0395           sizeof(BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U >(0)) \
0396               == sizeof(boost::mpl::aux::yes_tag) \
0397       /**/
0398 #   else
0399 #     if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES
0400 #       define BOOST_MPL_HAS_MEMBER_TEST(args) \
0401           sizeof( \
0402               BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
0403                   static_cast< boost::mpl::aux::type_wrapper< U >* >(0) \
0404               ) \
0405           ) == sizeof(boost::mpl::aux::yes_tag) \
0406         /**/
0407 #     else
0408 #       define BOOST_MPL_HAS_MEMBER_TEST(args) \
0409           sizeof( \
0410               BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
0411                   static_cast< U* >(0) \
0412               ) \
0413           ) == sizeof(boost::mpl::aux::yes_tag) \
0414         /**/
0415 #     endif
0416 #   endif
0417 
0418 #   define BOOST_MPL_HAS_MEMBER_INTROSPECT( \
0419                args, substitute_macro, member_macro \
0420            ) \
0421       template< typename U > \
0422       struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) { \
0423           BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \
0424           BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
0425           BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
0426           BOOST_STATIC_CONSTANT( \
0427               bool, value = BOOST_MPL_HAS_MEMBER_TEST(args) \
0428           ); \
0429           typedef boost::mpl::bool_< value > type; \
0430       }; \
0431     /**/
0432 
0433 #   define BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
0434                args, introspect_macro, substitute_macro, member_macro \
0435            ) \
0436       template< \
0437           typename T \
0438         , typename fallback_ \
0439               = boost::mpl::bool_< BOOST_PP_ARRAY_ELEM(3, args) > \
0440       > \
0441       class BOOST_PP_ARRAY_ELEM(0, args) { \
0442           introspect_macro(args, substitute_macro, member_macro) \
0443       public: \
0444           static const bool value \
0445               = BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< T >::value; \
0446           typedef typename BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< \
0447               T \
0448           >::type type; \
0449       }; \
0450     /**/
0451 
0452 // BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE expands to the full
0453 // implementation of the function-based metafunction. Compile with -E
0454 // to see the preprocessor output for this macro.
0455 #   define BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \
0456                args, substitute_macro, member_macro \
0457            ) \
0458       BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
0459           args \
0460         , BOOST_MPL_HAS_MEMBER_INTROSPECT \
0461         , substitute_macro \
0462         , member_macro \
0463       ) \
0464     /**/
0465 
0466 #   if BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE
0467 
0468 #     if !defined(BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE)
0469 #       if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
0470 #         define BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE 1
0471 #       endif
0472 #     endif
0473 
0474 #     if !BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE
0475 #       define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
0476                    args, n \
0477                ) \
0478           BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
0479         /**/
0480 #     else
0481 #       define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
0482                    args, n \
0483                ) \
0484           BOOST_PP_CAT( \
0485               boost_mpl_has_xxx_ \
0486             , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
0487           ) \
0488         /**/
0489 #     endif
0490 
0491 #     define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME( \
0492                  args \
0493              ) \
0494         BOOST_PP_CAT( \
0495             BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
0496                 args, 0 \
0497             ) \
0498           , _tag \
0499         ) \
0500       /**/
0501 
0502 #     define BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
0503                  z, n, args \
0504              ) \
0505         template< \
0506              template< BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(n), typename U) > class U \
0507         > \
0508         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
0509                 args, n \
0510                ) { \
0511             typedef \
0512                 BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \
0513                 type; \
0514         }; \
0515       /**/
0516 
0517 #     define BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
0518                  args, substitute_macro \
0519              ) \
0520         typedef void \
0521             BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args); \
0522         BOOST_PP_REPEAT( \
0523             BOOST_PP_ARRAY_ELEM(2, args) \
0524           , BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE \
0525           , args \
0526         ) \
0527       /**/
0528 
0529 #     define BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE( \
0530                  args, member_macro \
0531              ) \
0532         template< \
0533             typename U \
0534           , typename V \
0535                 = BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \
0536         > \
0537         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) { \
0538             BOOST_STATIC_CONSTANT(bool, value = false); \
0539             typedef boost::mpl::bool_< value > type; \
0540         }; \
0541       /**/
0542 
0543 #     define BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT_WITH_TEMPLATE_SFINAE( \
0544                  z, n, args \
0545              ) \
0546         template< typename U > \
0547         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< \
0548             U \
0549           , typename \
0550                 BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
0551                     args, n \
0552                 )< \
0553                     BOOST_MSVC_TYPENAME U::BOOST_PP_ARRAY_ELEM(1, args)< > \
0554                 >::type \
0555         > { \
0556             BOOST_STATIC_CONSTANT(bool, value = true); \
0557             typedef boost::mpl::bool_< value > type; \
0558         }; \
0559       /**/
0560 
0561 #     define BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE( \
0562                  args, member_macro \
0563              ) \
0564         BOOST_PP_REPEAT( \
0565             BOOST_PP_ARRAY_ELEM(2, args) \
0566           , BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT_WITH_TEMPLATE_SFINAE \
0567           , args \
0568         ) \
0569       /**/
0570 
0571 #     define BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE( \
0572                  args, substitute_macro, member_macro \
0573              ) \
0574         BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE(args, member_macro) \
0575         BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE(args, member_macro) \
0576         template< typename U > \
0577         struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \
0578             : BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U > { \
0579         }; \
0580       /**/
0581  
0582 // BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE expands to the full
0583 // implementation of the template-based metafunction. Compile with -E
0584 // to see the preprocessor output for this macro.
0585 //
0586 // Note that if BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE is
0587 // defined BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE needs
0588 // to be expanded at namespace level before
0589 // BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE can be used.
0590 #     define BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \
0591                  args, substitute_macro, member_macro \
0592              ) \
0593         BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
0594             args, substitute_macro \
0595         ) \
0596         BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
0597             args \
0598           , BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE \
0599           , substitute_macro \
0600           , member_macro \
0601         ) \
0602       /**/
0603 
0604 #   endif // BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE
0605 
0606 // Note: In the current implementation the parameter and access macros
0607 // are no longer expanded.
0608 #   if !BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
0609 #     define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
0610         BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \
0611             ( 4, ( trait, name, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, default_ ) ) \
0612           , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \
0613           , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \
0614         ) \
0615       /**/
0616 #   else
0617 #     define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
0618         BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \
0619             ( 4, ( trait, name, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, default_ ) ) \
0620           , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \
0621           , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \
0622         ) \
0623       /**/
0624 #   endif
0625 
0626 #else // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
0627 
0628 // placeholder implementation
0629 
0630 #   define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
0631       template< typename T \
0632               , typename fallback_ = boost::mpl::bool_< default_ > > \
0633       struct trait { \
0634           BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
0635           typedef fallback_ type; \
0636       }; \
0637     /**/
0638 
0639 #endif // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
0640 
0641 #   define BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name) \
0642       BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF( \
0643           BOOST_PP_CAT(has_, name), name, false \
0644       ) \
0645     /**/
0646 
0647 #endif // BOOST_MPL_HAS_XXX_HPP_INCLUDED