Index: boost/mpl/has_xxx.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/mpl/has_xxx.hpp,v retrieving revision 1.5 diff -d -u -r1.5 has_xxx.hpp --- boost/mpl/has_xxx.hpp 9 Nov 2006 01:14:10 -0000 1.5 +++ boost/mpl/has_xxx.hpp 2 Apr 2007 22:33:37 -0000 @@ -4,6 +4,7 @@ // Copyright Aleksey Gurtovoy 2002-2006 // Copyright David Abrahams 2002-2003 +// Copyright Daniel Walker 2007 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -18,13 +19,18 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include +#include +#include #if !defined(BOOST_MPL_CFG_NO_HAS_XXX) @@ -230,4 +236,554 @@ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) \ /**/ +#if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) + +// Create boolean n-ary Metafunction to detect a nested template +// member with n template parameters. This implementation is based on +// a USENET newsgroup's posting by Aleksey Gurtovoy +// (comp.lang.c++.moderated, 2002-03-19), Rani Sharoni's USENET +// posting cited above, the non-template has_xxx implementations +// above, and discussion on the Boost mailing list. + +# if !defined(BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES) +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) +# define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 1 +# endif +# endif + +# if !defined(BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION) +# if (defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS) \ + || BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, <= 0x0303)) +# define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 1 +# endif +# endif + +# if !defined(BOOST_MPL_HAS_XXX_NO_IMPLICIT_SUBSTITUTE_TEMPLATE) +# if BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, <= 0x0303) +# define BOOST_MPL_HAS_XXX_NO_IMPLICIT_SUBSTITUTE_TEMPLATE 1 +# endif +# endif + +# if !defined(BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE) +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) +# define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 1 +# endif +# endif + +// NOTE: All internal implementation macros take a Boost.Preprocessor +// array argument called args which contains the arguments passed to +// HAS_XXX_TEMPLATE_NAMED_DEF and is of the following form. +// ( 4, ( trait, name, n, default_ ) ) + +# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \ + BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _introspect) \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args) \ + BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _substitute) \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) \ + BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _test) \ + /**/ + +// Thanks to Guillaume Melquiond for pointing out the need for the +// "substitute" template as an argument to the overloaded test +// functions to get SFINAE to work for member templates with the +// correct name but incorrect arguments. +# define BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \ + template< substitute_macro(args, V) > \ + struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args) { \ + }; \ + /**/ + +# if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION +# define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \ + template< typename V > \ + static boost::mpl::aux::no_tag \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \ + static boost::mpl::aux::no_tag \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \ + /**/ +# endif + +# if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES +# define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \ + template< typename V > \ + static boost::mpl::aux::yes_tag \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \ + boost::mpl::aux::type_wrapper< V > const volatile* \ + , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args) < \ + member_macro(args, V, T) \ + >* = 0 \ + ); \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \ + template< typename V > \ + static boost::mpl::aux::yes_tag \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \ + V const volatile* \ + , member_macro(args, V, T)* = 0 \ + ); \ + /**/ +# endif + +# if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION +# define BOOST_MPL_HAS_MEMBER_TEST(args) \ + sizeof(BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U >(0)) \ + == sizeof(boost::mpl::aux::yes_tag) \ + /**/ +# else +# if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES +# define BOOST_MPL_HAS_MEMBER_TEST(args) \ + sizeof( \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \ + static_cast< boost::mpl::aux::type_wrapper< U >* >(0) \ + ) \ + ) == sizeof(boost::mpl::aux::yes_tag) \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_TEST(args) \ + sizeof( \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \ + static_cast< U* >(0) \ + ) \ + ) == sizeof(boost::mpl::aux::yes_tag) \ + /**/ +# endif +# endif + +# define BOOST_MPL_HAS_MEMBER_INTROSPECT( \ + args, substitute_macro, member_macro \ + ) \ + template< typename U > \ + struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) { \ + BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \ + BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \ + BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \ + BOOST_STATIC_CONSTANT( \ + bool, value = BOOST_MPL_HAS_MEMBER_TEST(args) \ + ); \ + typedef boost::mpl::bool_< value > type; \ + }; \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \ + args, introspect_macro, substitute_macro, member_macro \ + ) \ + template< \ + typename T \ + BOOST_PP_ENUM_TRAILING_PARAMS( \ + BOOST_PP_ARRAY_ELEM(2, args), typename T \ + ) \ + , typename fallback_ \ + = boost::mpl::bool_< BOOST_PP_ARRAY_ELEM(3, args) > \ + > \ + class BOOST_PP_ARRAY_ELEM(0, args) { \ + introspect_macro(args, substitute_macro, member_macro) \ + public: \ + static const bool value \ + = BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< T >::value; \ + typedef typename BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< \ + T \ + >::type type; \ + }; \ + /**/ + +// For example, +// BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( +// (4, (has_xxx, xxx, 2, false)) +// , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER +// , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS +// ) +// expands to something like the following... +// +// template< +// typename T , typename T0 , typename T1 +// , typename fallback_ = boost::mpl::bool_< false > +// > +// class has_xxx { +// template< typename U > +// struct has_xxx_introspect { +// template< template< typename V0 , typename V1 > class V > +// struct has_xxx_substitute { +// }; +// +// template< typename V > +// static boost::mpl::aux::no_tag +// has_xxx_test(...); +// +// template< typename V > +// static boost::mpl::aux::yes_tag +// has_xxx_test( +// boost::mpl::aux::type_wrapper< V > const volatile* +// , has_xxx_substitute < V::template xxx >* = 0 +// ); +// +// static const bool value +// = sizeof(has_xxx_test< U >(0)) +// == sizeof(boost::mpl::aux::yes_tag); +// typedef boost::mpl::bool_< value > type; +// }; +// public: +// static const bool value = has_xxx_introspect< T >::value; +// typedef typename has_xxx_introspect< T >::type type; +// }; +# define BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \ + args \ + , BOOST_MPL_HAS_MEMBER_INTROSPECT \ + , substitute_macro \ + , member_macro \ + ) \ + /**/ + +# if BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE + +# if !defined(BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE) +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) +# define BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE 1 +# endif +# endif + +# if !BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE +# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \ + args \ + ) \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args) \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \ + args \ + ) \ + BOOST_PP_CAT( \ + boost_mpl_has_xxx_ \ + , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args) \ + ) \ + /**/ +# endif + +# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME( \ + args \ + ) \ + BOOST_PP_CAT( \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \ + args \ + ) \ + , _tag \ + ) \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro \ + ) \ + typedef void \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args); \ + template< substitute_macro(args, U) > \ + struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \ + args \ + ) { \ + typedef \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \ + type; \ + }; \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE( \ + args, member_macro \ + ) \ + template< \ + typename U \ + BOOST_PP_ENUM_TRAILING_PARAMS( \ + BOOST_PP_ARRAY_ELEM(2, args), typename U \ + ) \ + , typename V \ + = BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \ + > \ + struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) { \ + BOOST_STATIC_CONSTANT(bool, value = false); \ + typedef boost::mpl::bool_< value > type; \ + }; \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE( \ + args, member_macro \ + ) \ + template< \ + typename U \ + BOOST_PP_ENUM_TRAILING_PARAMS( \ + BOOST_PP_ARRAY_ELEM(2, args), typename U \ + ) \ + > \ + struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< \ + U BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ARRAY_ELEM(2, args), U) \ + , typename \ + BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \ + args \ + )< \ + member_macro(args, U, U) \ + >::type \ + > { \ + BOOST_STATIC_CONSTANT(bool, value = true); \ + typedef boost::mpl::bool_< value > type; \ + }; \ + /**/ + +# define BOOST_MPL_HAS_MEMBER_BASIC_INTROSPECT_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE(args, member_macro) \ + BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE(args, member_macro) \ + template< typename U > \ + struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \ + : BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< \ + U \ + BOOST_PP_ENUM_TRAILING_PARAMS( \ + BOOST_PP_ARRAY_ELEM(2, args) \ + , T \ + ) \ + > { \ + }; \ + /**/ + +# if !BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE +# define BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_BASIC_INTROSPECT_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_BASIC_INTROSPECT_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + /**/ +# endif + +// For example, +// BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( +// (4, (has_xxx, xxx, 2, false)) +// , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER +// , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS +// ) +// expands to something like the following... +// +// template< +// typename T , typename T0 , typename T1 +// , typename fallback_ = boost::mpl::bool_< false > +// > +// class has_xxx { +// typedef void has_xxx_substitute_tag; +// +// template< template< typename U0 , typename U1 > class U > +// struct has_xxx_substitute { +// typedef has_xxx_substitute_tag type; +// }; +// +// template< +// typename U , typename U0 , typename U1 +// , typename V = has_xxx_substitute_tag +// > +// struct has_xxx_test { +// static const bool value = false; +// typedef boost::mpl::bool_< value > type; +// }; +// +// template< typename U , typename U0 , typename U1 > +// struct has_xxx_test< +// U , U0 , U1 +// , typename has_xxx_substitute< U::template xxx >::type +// > { +// static const bool value = true; +// typedef boost::mpl::bool_< value > type; +// }; +// +// template< typename U > +// struct has_xxx_introspect : has_xxx_test< U , T0 , T1 > { +// }; +// public: +// static const bool value = has_xxx_introspect< T >::value; +// typedef typename has_xxx_introspect< T >::type type; +// }; +// +// Note that if BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE is +// defined BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE needs +// to be expanded at namespace level before +// BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE can be used. +# define BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro, member_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \ + args \ + , BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE \ + , substitute_macro \ + , member_macro \ + ) \ + /**/ + +# endif // BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE + +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_EXPLICIT_SUBSTITUTE_PARAMETER( \ + args, param \ + ) \ + typename \ + /**/ + +# if !BOOST_MPL_HAS_XXX_NO_IMPLICIT_SUBSTITUTE_TEMPLATE +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_IMPLICIT_SUBSTITUTE_PARAMETER( \ + args, param \ + ) \ + template< \ + BOOST_PP_ENUM_PARAMS(BOOST_PP_ARRAY_ELEM(2, args), typename param) \ + > \ + class param\ + /**/ + +// See comment at BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS below. +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER(args, param) \ + BOOST_PP_IF( \ + BOOST_PP_ARRAY_ELEM(2, args) \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_IMPLICIT_SUBSTITUTE_PARAMETER \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_EXPLICIT_SUBSTITUTE_PARAMETER \ + ) ( args, param ) \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER(args, param) \ + BOOST_MPL_HAS_MEMBER_TEMPLATE_EXPLICIT_SUBSTITUTE_PARAMETER( \ + args, param \ + ) \ + /**/ +# endif + +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_EXPLICIT_ACCESS( \ + args, class_type, param \ + ) \ + typename class_type::template BOOST_PP_ARRAY_ELEM(1, args)< \ + BOOST_PP_ENUM_PARAMS(BOOST_PP_ARRAY_ELEM(2, args), param) \ + > \ + /**/ + +# if !BOOST_MPL_HAS_XXX_NO_IMPLICIT_SUBSTITUTE_TEMPLATE +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_IMPLICIT_ACCESS( \ + args, class_type, param \ + ) \ + class_type::template BOOST_PP_ARRAY_ELEM(1, args) \ + /**/ + +// Note: to recognize templates with no required arguments use +// explicit access since a substitute template with no args cannot be +// declared. +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS(args, class_type, param) \ + BOOST_PP_IF( \ + BOOST_PP_ARRAY_ELEM(2, args) \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_IMPLICIT_ACCESS \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_EXPLICIT_ACCESS \ + ) ( args, class_type, param ) \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS(args, class_type, param) \ + BOOST_MPL_HAS_MEMBER_TEMPLATE_EXPLICIT_ACCESS( \ + args, class_type, param \ + ) \ + /**/ +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) +// MSVC (7.1, 8.0) accepts the member template access syntax below +// regardless of the member template's arity. introspect will reject +// member templates with the wrong arity due to the substitute +// template. Note that using this syntax also enables MSVC +// template-based SFINAE to reject non-template members. This is +// important because explicitly passing the template args will match +// templates with the correct name and arguments but will cause ICE on +// non-template members. However, MSVC nullary template-based SFINAE +// (introspection for a member template with no required args) can not +// reject non-template members, but MSVC function-based SFINAE +// can. So, one of the two is chosen based on the number of required +// template parameters. +# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS_MSVC( \ + args, class_type, param \ + ) \ + typename class_type::template BOOST_PP_ARRAY_ELEM(1, args)< > \ + /**/ +# else +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS_MSVC( \ + args, class_type, param \ + ) \ + class_type::BOOST_PP_ARRAY_ELEM(1, agrs)< > \ + /**/ +# endif + +# define BOOST_MPL_HAS_MEMBER_TEMPLATE_MSVC( \ + args, substitute_macro, member_macro \ + ) \ + BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \ + args, substitute_macro \ + ) \ + BOOST_PP_IF( \ + BOOST_PP_ARRAY_ELEM(2, args) \ + , BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE \ + , BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE \ + ) ( \ + args \ + , substitute_macro \ + , member_macro \ + ) \ + /**/ +# endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) +# define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, n, default_) \ + BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \ + ( 4, ( trait, name, n, default_ ) ) \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \ + ) \ + /**/ +# else +# define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, n, default_) \ + BOOST_MPL_HAS_MEMBER_TEMPLATE_MSVC( \ + ( 4, ( trait, name, n, default_ ) ) \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \ + , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS_MSVC \ + ) \ + /**/ +# endif + +#else // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE + +// placeholder implementation + +# define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, n, default_) \ + template< typename T \ + BOOST_PP_ENUM_TRAILING_PARAMS(n, typename U) \ + , typename fallback_ = boost::mpl::bool_< default_ > > \ + struct trait { \ + BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \ + typedef fallback_ type; \ + }; \ + /**/ + +#endif // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE + +# define BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name, n) \ + BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF( \ + BOOST_PP_CAT(has_, name), name, n, false \ + ) \ + /**/ + #endif // BOOST_MPL_HAS_XXX_HPP_INCLUDED Index: boost/mpl/aux_/config/has_xxx.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/mpl/aux_/config/has_xxx.hpp,v retrieving revision 1.3 diff -d -u -r1.3 has_xxx.hpp --- boost/mpl/aux_/config/has_xxx.hpp 3 Sep 2004 15:56:56 -0000 1.3 +++ boost/mpl/aux_/config/has_xxx.hpp 2 Apr 2007 22:33:37 -0000 @@ -27,6 +27,7 @@ ) # define BOOST_MPL_CFG_NO_HAS_XXX +# define BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE #endif Index: libs/mpl/doc/src/refmanual/CFG_NO_HAS_XXX_TEMPLATE.rst =================================================================== RCS file: libs/mpl/doc/src/refmanual/CFG_NO_HAS_XXX_TEMPLATE.rst diff -N libs/mpl/doc/src/refmanual/CFG_NO_HAS_XXX_TEMPLATE.rst --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libs/mpl/doc/src/refmanual/CFG_NO_HAS_XXX_TEMPLATE.rst 2 Apr 2007 22:33:53 -0000 @@ -0,0 +1,27 @@ +.. Macros/Configuration//BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE |20 + +BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE +======================== + +Synopsis +-------- + +.. parsed-literal:: + + // #define BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE + + +Description +----------- + +``BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE`` is a boolean configuration +macro signaling availability of the |BOOST_MPL_HAS_XXX_TEMPLATE_DEF| / +|BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF| introspection macros' +functionality on a particular compiler. + + +See also +-------- + +|Macros|, |Configuration|, |BOOST_MPL_HAS_XXX_TEMPLATE_DEF|, |BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF| + Index: libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_DEF.rst =================================================================== RCS file: libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_DEF.rst diff -N libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_DEF.rst --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_DEF.rst 2 Apr 2007 22:33:53 -0000 @@ -0,0 +1,120 @@ +.. Macros/Introspection//BOOST_MPL_HAS_XXX_TEMPLATE_DEF + +BOOST_MPL_HAS_XXX_TEMPLATE_DEF +=========================== + +Synopsis +-------- + +.. parsed-literal:: + + #define BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name, n) \\ + |unspecified-token-seq| \\ + /\*\*/ + + +Description +----------- + +Expands into a definition of a boolean n-ary |Metafunction| +``has_name`` such that for any types ``x, a1, a2, ..., an`` +``has_name::value == true`` if and only if ``x`` is a +class type and has a nested template member ``x::template name``. + +On the deficient compilers not capable of performing the detection, +``has_name::value`` always returns ``false``. A +boolean configuration macro, |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE|, is +provided to signal or override the "deficient" status of a particular +compiler. + +|Note:| |BOOST_MPL_HAS_XXX_TEMPLATE_DEF| is a simplified front end to +the |BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF| introspection macro |-- end +note| + + +Header +------ + +.. parsed-literal:: + + #include + + +Parameters +---------- + + ++---------------+-------------------------------+---------------------------------------------------+ +| Parameter | Requirement | Description | ++===============+===============================+===================================================+ +| ``name`` | A legal identifier token | A name of the template member being detected. | ++---------------+-------------------------------+---------------------------------------------------+ +| ``n`` | An integral constant >= 0 | The arity of the template member being detected. | ++---------------+-------------------------------+---------------------------------------------------+ + + +Expression semantics +-------------------- + +For any legal C++ identifier ``name`` and integral constant expression +``n`` greater than or equal to 0: + +.. parsed-literal:: + + BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name, n) + +:Precondition: + Appears at namespace scope. + +:Return type: + None. + +:Semantics: + Equivalent to + + .. parsed-literal:: + + BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF( + BOOST_PP_CAT(has\_,name), name, n, false + ) + + +Example +------- + +.. parsed-literal:: + + BOOST_MPL_HAS_XXX_TEMPLATE_DEF(xxx, 1) + + struct test1 {}; + struct test2 { void xxx(); }; + struct test3 { int xxx; }; + struct test4 { static int xxx(); }; + struct test5 { typedef int xxx; }; + struct test6 { struct xxx; }; + struct test7 { typedef void (*xxx)(); }; + struct test8 { typedef void (xxx)(); }; + struct test9 { template< class T > struct xxx {}; }; + + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + + #if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) + BOOST_MPL_ASSERT(( has_xxx )); + #endif + + BOOST_MPL_ASSERT(( has_xxx )); + + +See also +-------- + +|Macros|, |BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF|, |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE| + Index: libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_NAMED_DEF.rst =================================================================== RCS file: libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_NAMED_DEF.rst diff -N libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_NAMED_DEF.rst --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_NAMED_DEF.rst 2 Apr 2007 22:33:53 -0000 @@ -0,0 +1,165 @@ +.. Macros/Introspection//BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF + +BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF +================================= + +Synopsis +-------- + +.. parsed-literal:: + + #define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, n, default\_) \\ + |unspecified-token-seq| \\ + /\*\*/ + + +Description +----------- + +Expands into a definition of a boolean n-ary |Metafunction| ``trait`` +such that for any types ``x, a1, a2, ..., an`` ``trait::value == true`` if and only if ``x`` is a class type and has a +nested template member ``x::template name``. + +On the deficient compilers not capable of performing the detection, +``trait::value`` always returns a fallback value +``default_``. A boolean configuration macro, +|BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE|, is provided to signal or override +the "deficient" status of a particular compiler. |Note:| The fallback +value can also be provided at the point of the metafunction +invocation; see the `Expression semantics` section for details |-- end +note| + + +Header +------ + +.. parsed-literal:: + + #include + + +Parameters +---------- + ++---------------+-------------------------------+---------------------------------------------------+ +| Parameter | Requirement | Description | ++===============+===============================+===================================================+ +| ``trait`` | A legal identifier token | A name of the metafunction to be generated. | ++---------------+-------------------------------+---------------------------------------------------+ +| ``name`` | A legal identifier token | A name of the member being detected. | ++---------------+-------------------------------+---------------------------------------------------+ +| ``n`` | An integral constant >= 0 | The arity of the template member being detected. | ++---------------+-------------------------------+---------------------------------------------------+ +| ``default_`` | An boolean constant | A fallback value for the deficient compilers. | ++---------------+-------------------------------+---------------------------------------------------+ + + +Expression semantics +-------------------- + +For any legal C++ identifiers ``trait`` and ``name``, integral +constant expression ``n`` greater than or equal to 0, boolean constant +expression ``c1``, boolean |Integral Constant| ``c2``, and arbitrary +type ``x``: + +.. parsed-literal:: + + BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, n, c1) + +:Precondition: + Appears at namespace scope. + +:Return type: + None. + +:Semantics: + Expands into an equivalent of the following class template + definition + + .. parsed-literal:: + + template< + typename X + , typename A1, ..., typename An + , typename fallback = boost::mpl::bool_ + > + struct trait + { + // |unspecified| + // ... + }; + + where ``trait`` is a boolean |Metafunction| with the following + semantics: + + .. parsed-literal:: + + typedef trait::type r; + + :Return type: + |Integral Constant|. + + :Semantics: + If |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE| is defined, ``r::value + == c1``; otherwise, ``r::value == true`` if and only if ``x`` + is a class type that has a nested type member ``x::template + name``. + + + .. parsed-literal:: + + typedef trait< x, a1, ..., an, c2 >::type r; + + :Return type: + |Integral Constant|. + + :Semantics: + If |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE| is defined, ``r::value + == c2::value``; otherwise, equivalent to + + .. parsed-literal:: + + typedef trait::type r; + + +Example +------- + +.. parsed-literal:: + + BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF( + has_xxx, xxx, 1, false + ) + + struct test1 {}; + struct test2 { void xxx(); }; + struct test3 { int xxx; }; + struct test4 { static int xxx(); }; + struct test5 { typedef int xxx; }; + struct test6 { struct xxx; }; + struct test7 { typedef void (*xxx)(); }; + struct test8 { typedef void (xxx)(); }; + struct test9 { template< class T > struct xxx {}; }; + + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + BOOST_MPL_ASSERT_NOT(( has_xxx )); + + #if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) + BOOST_MPL_ASSERT(( has_xxx )); + #endif + + BOOST_MPL_ASSERT(( has_xxx )); + + +See also +-------- + +|Macros|, |BOOST_MPL_HAS_XXX_TEMPLATE_DEF|, |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE| + Index: libs/mpl/test/has_xxx.cpp =================================================================== RCS file: /cvsroot/boost/boost/libs/mpl/test/has_xxx.cpp,v retrieving revision 1.4 diff -d -u -r1.4 has_xxx.cpp --- libs/mpl/test/has_xxx.cpp 18 Sep 2004 07:18:02 -0000 1.4 +++ libs/mpl/test/has_xxx.cpp 2 Apr 2007 22:33:58 -0000 @@ -1,5 +1,6 @@ // Copyright Aleksey Gurtovoy 2000-2004 +// Copyright Daniel Walker 2007 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +17,12 @@ #include BOOST_MPL_HAS_XXX_TRAIT_DEF(xxx) +BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_xxx0, xxx, 0, false) +BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_xxx1, xxx, 1, false) +BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(has_xxx2, xxx, 2, false) +BOOST_MPL_HAS_XXX_TEMPLATE_DEF(yyy0, 0) +BOOST_MPL_HAS_XXX_TEMPLATE_DEF(yyy1, 1) +BOOST_MPL_HAS_XXX_TEMPLATE_DEF(yyy2, 2) struct a1 {}; struct a2 { void xxx(); }; @@ -31,6 +38,13 @@ struct b6 { typedef void (*xxx)(); }; struct b7 { typedef void (xxx)(); }; +struct c0 { template< typename T0 = int > struct xxx {}; }; +struct c1 { template< typename T1 > struct xxx {}; }; +struct c2 { template< typename T1, typename T2 > struct xxx {}; }; +struct c3 { template< typename T0 = int > struct yyy0 {}; }; +struct c4 { template< typename T1 > struct yyy1 {}; }; +struct c5 { template< typename T1, typename T2 > struct yyy2 {}; }; + template< typename T > struct outer; template< typename T > struct inner { typedef typename T::type type; }; @@ -42,25 +56,195 @@ MPL_TEST_CASE() { MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< int > )); + MPL_ASSERT_NOT(( has_xxx1< int, int > )); + MPL_ASSERT_NOT(( has_xxx2< int, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< int > )); + MPL_ASSERT_NOT(( has_yyy1< int, int > )); + MPL_ASSERT_NOT(( has_yyy2< int, int, int > )); + #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< int& > )); + MPL_ASSERT_NOT(( has_xxx1< int&, int > )); + MPL_ASSERT_NOT(( has_xxx2< int&, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< int& > )); + MPL_ASSERT_NOT(( has_yyy1< int&, int > )); + MPL_ASSERT_NOT(( has_yyy2< int&, int, int > )); + MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< int* > )); + MPL_ASSERT_NOT(( has_xxx1< int*, int > )); + MPL_ASSERT_NOT(( has_xxx2< int*, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< int* > )); + MPL_ASSERT_NOT(( has_yyy1< int*, int > )); + MPL_ASSERT_NOT(( has_yyy2< int*, int, int > )); + MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< int[] > )); + MPL_ASSERT_NOT(( has_xxx1< int[], int > )); + MPL_ASSERT_NOT(( has_xxx2< int[], int, int > )); + MPL_ASSERT_NOT(( has_yyy0< int[] > )); + MPL_ASSERT_NOT(( has_yyy1< int[], int > )); + MPL_ASSERT_NOT(( has_yyy2< int[], int, int > )); + MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< int (*)() > )); + MPL_ASSERT_NOT(( has_xxx1< int (*)(), int > )); + MPL_ASSERT_NOT(( has_xxx2< int (*)(), int, int > )); + MPL_ASSERT_NOT(( has_yyy0< int (*)() > )); + MPL_ASSERT_NOT(( has_yyy1< int (*)(), int > )); + MPL_ASSERT_NOT(( has_yyy2< int (*)(), int, int > )); MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< a2 > )); + MPL_ASSERT_NOT(( has_xxx1< a2, int > )); + MPL_ASSERT_NOT(( has_xxx2< a2, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< a2 > )); + MPL_ASSERT_NOT(( has_yyy1< a2, int > )); + MPL_ASSERT_NOT(( has_yyy2< a2, int, int > )); + MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< a3 > )); + MPL_ASSERT_NOT(( has_xxx1< a3, int > )); + MPL_ASSERT_NOT(( has_xxx2< a3, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< a3 > )); + MPL_ASSERT_NOT(( has_yyy1< a3, int > )); + MPL_ASSERT_NOT(( has_yyy2< a3, int, int > )); + MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< a4 > )); + MPL_ASSERT_NOT(( has_xxx1< a4, int > )); + MPL_ASSERT_NOT(( has_xxx2< a4, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< a4 > )); + MPL_ASSERT_NOT(( has_yyy1< a4, int > )); + MPL_ASSERT_NOT(( has_yyy2< a4, int, int > )); + #if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) MPL_ASSERT_NOT(( has_xxx )); #endif MPL_ASSERT_NOT(( has_xxx< enum_ > )); + MPL_ASSERT_NOT(( has_xxx0< enum_ > )); + MPL_ASSERT_NOT(( has_xxx1< enum_, int > )); + MPL_ASSERT_NOT(( has_xxx2< enum_, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< enum_ > )); + MPL_ASSERT_NOT(( has_yyy1< enum_, int > )); + MPL_ASSERT_NOT(( has_yyy2< enum_, int, int > )); #endif + MPL_ASSERT_NOT(( has_xxx )); + MPL_ASSERT_NOT(( has_xxx0< a1 > )); + MPL_ASSERT_NOT(( has_xxx1< a1, int > )); + MPL_ASSERT_NOT(( has_xxx2< a1, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< a1 > )); + MPL_ASSERT_NOT(( has_yyy1< a1, int > )); + MPL_ASSERT_NOT(( has_yyy2< a1, int, int > )); + MPL_ASSERT_NOT(( has_xxx< outer< inner > > )); + MPL_ASSERT_NOT(( has_xxx0< outer< inner > > )); + MPL_ASSERT_NOT(( has_xxx1< outer< inner >, int > )); + MPL_ASSERT_NOT(( has_xxx2< outer< inner >, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< outer< inner > > )); + MPL_ASSERT_NOT(( has_yyy1< outer< inner >, int > )); + MPL_ASSERT_NOT(( has_yyy2< outer< inner >, int, int > )); + MPL_ASSERT_NOT(( has_xxx< incomplete > )); + MPL_ASSERT_NOT(( has_xxx0< incomplete > )); + MPL_ASSERT_NOT(( has_xxx1< incomplete, int > )); + MPL_ASSERT_NOT(( has_xxx2< incomplete, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< incomplete > )); + MPL_ASSERT_NOT(( has_yyy1< incomplete, int > )); + MPL_ASSERT_NOT(( has_yyy2< incomplete, int, int > )); + MPL_ASSERT_NOT(( has_xxx< abstract > )); + MPL_ASSERT_NOT(( has_xxx0< abstract > )); + MPL_ASSERT_NOT(( has_xxx1< abstract, int > )); + MPL_ASSERT_NOT(( has_xxx2< abstract, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< abstract > )); + MPL_ASSERT_NOT(( has_yyy1< abstract, int > )); + MPL_ASSERT_NOT(( has_yyy2< abstract, int, int > )); + MPL_ASSERT_NOT(( has_xxx< noncopyable > )); + MPL_ASSERT_NOT(( has_xxx0< noncopyable > )); + MPL_ASSERT_NOT(( has_xxx1< noncopyable, int > )); + MPL_ASSERT_NOT(( has_xxx2< noncopyable, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< noncopyable > )); + MPL_ASSERT_NOT(( has_yyy1< noncopyable, int > )); + MPL_ASSERT_NOT(( has_yyy2< noncopyable, int, int > )); + +#if !BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4308)) + MPL_ASSERT_NOT(( has_xxx0< b1 > )); + MPL_ASSERT_NOT(( has_xxx1< b1, int > )); + MPL_ASSERT_NOT(( has_xxx2< b1, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b1 > )); + MPL_ASSERT_NOT(( has_yyy1< b1, int > )); + MPL_ASSERT_NOT(( has_yyy2< b1, int, int > )); + + MPL_ASSERT_NOT(( has_xxx0< b2 > )); + MPL_ASSERT_NOT(( has_xxx1< b2, int > )); + MPL_ASSERT_NOT(( has_xxx2< b2, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b2 > )); + MPL_ASSERT_NOT(( has_yyy1< b2, int > )); + MPL_ASSERT_NOT(( has_yyy2< b2, int, int > )); + + MPL_ASSERT_NOT(( has_xxx0< b3 > )); + MPL_ASSERT_NOT(( has_xxx1< b3, int > )); + MPL_ASSERT_NOT(( has_xxx2< b3, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b3 > )); + MPL_ASSERT_NOT(( has_yyy1< b3, int > )); + MPL_ASSERT_NOT(( has_yyy2< b3, int, int > )); + + MPL_ASSERT_NOT(( has_xxx0< b4 > )); + MPL_ASSERT_NOT(( has_xxx1< b4, int > )); + MPL_ASSERT_NOT(( has_xxx2< b4, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b4 > )); + MPL_ASSERT_NOT(( has_yyy1< b4, int > )); + MPL_ASSERT_NOT(( has_yyy2< b4, int, int > )); + + MPL_ASSERT_NOT(( has_xxx0< b5 > )); + MPL_ASSERT_NOT(( has_xxx1< b5, int > )); + MPL_ASSERT_NOT(( has_xxx2< b5, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b5 > )); + MPL_ASSERT_NOT(( has_yyy1< b5, int > )); + MPL_ASSERT_NOT(( has_yyy2< b5, int, int > )); + + MPL_ASSERT_NOT(( has_xxx0< b6 > )); + MPL_ASSERT_NOT(( has_xxx1< b6, int > )); + MPL_ASSERT_NOT(( has_xxx2< b6, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b6 > )); + MPL_ASSERT_NOT(( has_yyy1< b6, int > )); + MPL_ASSERT_NOT(( has_yyy2< b6, int, int > )); + + MPL_ASSERT_NOT(( has_xxx0< b7 > )); + MPL_ASSERT_NOT(( has_xxx1< b7, int > )); + MPL_ASSERT_NOT(( has_xxx2< b7, int, int > )); + MPL_ASSERT_NOT(( has_yyy0< b7 > )); + MPL_ASSERT_NOT(( has_yyy1< b7, int > )); + MPL_ASSERT_NOT(( has_yyy2< b7, int, int > )); +#endif + + // Same name, different args. + // Note: has_xxx0 is not test here because it's impossible to + // declare a template with no arguments (only no required + // arguments), so there is no zero argument substitute template + // to reject n-ary member templates. +#if (!BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, <= 0x0303) \ + && !BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4308))) + MPL_ASSERT_NOT(( has_xxx1 )); + MPL_ASSERT_NOT(( has_xxx2 )); + MPL_ASSERT_NOT(( has_xxx2 )); +#endif + + // Different name, same args. + MPL_ASSERT_NOT(( has_xxx0 )); + MPL_ASSERT_NOT(( has_xxx1 )); + MPL_ASSERT_NOT(( has_xxx2 )); + + // Different name, different args. + MPL_ASSERT_NOT(( has_xxx0 )); + MPL_ASSERT_NOT(( has_xxx1 )); + MPL_ASSERT_NOT(( has_xxx2 )); + MPL_ASSERT_NOT(( has_xxx2 )); MPL_ASSERT(( has_xxx )); MPL_ASSERT(( has_xxx )); @@ -70,6 +254,15 @@ MPL_ASSERT(( has_xxx )); MPL_ASSERT(( has_xxx )); +#if !BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4308)) + MPL_ASSERT(( has_xxx0 )); + MPL_ASSERT(( has_yyy0 )); +#endif + MPL_ASSERT(( has_xxx1 )); + MPL_ASSERT(( has_xxx2 )); + MPL_ASSERT(( has_yyy1 )); + MPL_ASSERT(( has_yyy2 )); + #if !defined(HAS_XXX_ASSERT) # define HAS_XXX_ASSERT(x) MPL_ASSERT(x) #endif @@ -81,4 +274,17 @@ HAS_XXX_ASSERT(( has_xxx )); HAS_XXX_ASSERT(( has_xxx )); HAS_XXX_ASSERT(( has_xxx )); + +#if !defined(HAS_XXX_TEMPLATE_ASSERT) +# define HAS_XXX_TEMPLATE_ASSERT(x) MPL_ASSERT(x) +#endif + +#if !BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4308)) + HAS_XXX_TEMPLATE_ASSERT(( has_xxx0 )); + HAS_XXX_TEMPLATE_ASSERT(( has_yyy0 )); +#endif + HAS_XXX_TEMPLATE_ASSERT(( has_xxx1 )); + HAS_XXX_TEMPLATE_ASSERT(( has_xxx2 )); + HAS_XXX_TEMPLATE_ASSERT(( has_yyy1 )); + HAS_XXX_TEMPLATE_ASSERT(( has_yyy2 )); } Index: libs/mpl/test/no_has_xxx.cpp =================================================================== RCS file: /cvsroot/boost/boost/libs/mpl/test/no_has_xxx.cpp,v retrieving revision 1.2 diff -d -u -r1.2 no_has_xxx.cpp --- libs/mpl/test/no_has_xxx.cpp 2 Sep 2004 15:41:35 -0000 1.2 +++ libs/mpl/test/no_has_xxx.cpp 2 Apr 2007 22:33:58 -0000 @@ -23,4 +23,8 @@ # define HAS_XXX_ASSERT(x) MPL_ASSERT_NOT(x) #endif +#if defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) +# define HAS_XXX_TEMPLATE_ASSERT(x) MPL_ASSERT_NOT(x) +#endif + #include "has_xxx.cpp"