Add BOOST_MPL_HAS_XXX_TEMPLATE_DEF. Fixes #861

[SVN r62579]
This commit is contained in:
Steven Watanabe 2010-06-08 14:24:55 +00:00
parent 52d8442055
commit 360322e894
7 changed files with 1095 additions and 0 deletions

View File

@ -0,0 +1,32 @@
.. Macros/Configuration//BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE |20
.. Copyright Daniel Walker 2007.
.. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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|

View File

@ -0,0 +1,125 @@
.. Macros/Introspection//BOOST_MPL_HAS_XXX_TEMPLATE_DEF
.. Copyright Daniel Walker 2007.
.. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
BOOST_MPL_HAS_XXX_TEMPLATE_DEF
==============================
Synopsis
--------
.. parsed-literal::
#define BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name, n) \\
|unspecified-token-seq| \\
/\*\*/
Description
-----------
Expands into the definition of a boolean n-ary |Metafunction|
``has_name`` such that for any types ``x, a1, a2, ..., an``
``has_name<x, a1, ..., an>::value == true`` if and only if ``x`` is a
class type and has a nested template member ``x::template name<a1,
..., an>``.
On deficient compilers not capable of performing the detection,
``has_name<x, a1, ..., an>::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 <boost/mpl/has_xxx.hpp>
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<test1, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test2, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test3, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test4, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test5, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test6, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test7, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test8, int> ));
#if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
BOOST_MPL_ASSERT(( has_xxx<test9, int> ));
#endif
BOOST_MPL_ASSERT(( has_xxx<test9, int, true\_> ));
See also
--------
|Macros|, |BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF|, |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE|

View File

@ -0,0 +1,170 @@
.. Macros/Introspection//BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF
.. Copyright Daniel Walker 2007.
.. Distributed under the Boost
.. Software License, Version 1.0. (See accompanying
.. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 the definition of a boolean n-ary |Metafunction| ``trait``
such that for any types ``x, a1, a2, ..., an`` ``trait<x, a1, ...,
an>::value == true`` if and only if ``x`` is a class type and has a
nested template member ``x::template name<a1, ..., an>``.
On deficient compilers not capable of performing the detection,
``trait<x, a1, ..., an>::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 <boost/mpl/has_xxx.hpp>
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\_<c1>
>
struct trait
{
// |unspecified|
// ...
};
where ``trait`` is a boolean |Metafunction| with the following
semantics:
.. parsed-literal::
typedef trait<x, a1, ..., an>::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<a1, ..., an>``.
.. 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<x, a1, ..., an>::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<test1, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test2, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test3, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test4, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test5, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test6, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test7, int> ));
BOOST_MPL_ASSERT_NOT(( has_xxx<test8, int> ));
#if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
BOOST_MPL_ASSERT(( has_xxx<test9, int> ));
#endif
BOOST_MPL_ASSERT(( has_xxx<test9, int, true\_> ));
See also
--------
|Macros|, |BOOST_MPL_HAS_XXX_TEMPLATE_DEF|, |BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE|

View File

@ -27,6 +27,7 @@
)
# define BOOST_MPL_CFG_NO_HAS_XXX
# define BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
#endif

View File

@ -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 <boost/mpl/bool.hpp>
#include <boost/mpl/aux_/type_wrapper.hpp>
#include <boost/mpl/aux_/yes_no.hpp>
#include <boost/mpl/aux_/config/gcc.hpp>
#include <boost/mpl/aux_/config/has_xxx.hpp>
#include <boost/mpl/aux_/config/msvc_typename.hpp>
#include <boost/mpl/aux_/config/msvc.hpp>
#include <boost/mpl/aux_/config/static_constant.hpp>
#include <boost/mpl/aux_/config/workaround.hpp>
#include <boost/preprocessor/array/elem.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
# include <boost/type_traits/is_class.hpp>
@ -271,4 +277,555 @@ struct trait \
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, <= 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, <= 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, <= 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, <= 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, <= 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

View File

@ -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/aux_/test.hpp>
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 b5 { typedef int xxx[10]; };
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 @@ template< typename T > struct xxx;
MPL_TEST_CASE()
{
MPL_ASSERT_NOT(( has_xxx<int> ));
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<int&> ));
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<int*> ));
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<int[]> ));
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<int (*)()> ));
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<a2> ));
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<a3> ));
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<a4> ));
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<a5> ));
#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<a1> ));
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<int> > > ));
MPL_ASSERT_NOT(( has_xxx0< outer< inner<int> > > ));
MPL_ASSERT_NOT(( has_xxx1< outer< inner<int> >, int > ));
MPL_ASSERT_NOT(( has_xxx2< outer< inner<int> >, int, int > ));
MPL_ASSERT_NOT(( has_yyy0< outer< inner<int> > > ));
MPL_ASSERT_NOT(( has_yyy1< outer< inner<int> >, int > ));
MPL_ASSERT_NOT(( has_yyy2< outer< inner<int> >, 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<c2, int> ));
MPL_ASSERT_NOT(( has_xxx2<c0, int, int> ));
MPL_ASSERT_NOT(( has_xxx2<c1, int, int> ));
#endif
// Different name, same args.
MPL_ASSERT_NOT(( has_xxx0<c3> ));
MPL_ASSERT_NOT(( has_xxx1<c4, int> ));
MPL_ASSERT_NOT(( has_xxx2<c5, int, int> ));
// Different name, different args.
MPL_ASSERT_NOT(( has_xxx0<c4> ));
MPL_ASSERT_NOT(( has_xxx1<c5, int> ));
MPL_ASSERT_NOT(( has_xxx2<c3, int, int> ));
MPL_ASSERT_NOT(( has_xxx2<c4, int, int> ));
MPL_ASSERT(( has_xxx<b1,true_> ));
MPL_ASSERT(( has_xxx<b2,true_> ));
@ -70,6 +254,15 @@ MPL_TEST_CASE()
MPL_ASSERT(( has_xxx<b6,true_> ));
MPL_ASSERT(( has_xxx<b7,true_> ));
#if !BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4308)) && !BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
MPL_ASSERT(( has_xxx0<c0, true_> ));
MPL_ASSERT(( has_yyy0<c3, true_> ));
#endif
MPL_ASSERT(( has_xxx1<c1, int, true_> ));
MPL_ASSERT(( has_xxx2<c2, int, int, true_> ));
MPL_ASSERT(( has_yyy1<c4, int, true_> ));
MPL_ASSERT(( has_yyy2<c5, int, int, true_> ));
#if !defined(HAS_XXX_ASSERT)
# define HAS_XXX_ASSERT(x) MPL_ASSERT(x)
#endif
@ -81,4 +274,17 @@ MPL_TEST_CASE()
HAS_XXX_ASSERT(( has_xxx<b5> ));
HAS_XXX_ASSERT(( has_xxx<b6> ));
HAS_XXX_ASSERT(( has_xxx<b7> ));
#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)) && !BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
HAS_XXX_TEMPLATE_ASSERT(( has_xxx0<c0> ));
HAS_XXX_TEMPLATE_ASSERT(( has_yyy0<c3> ));
#endif
HAS_XXX_TEMPLATE_ASSERT(( has_xxx1<c1, int> ));
HAS_XXX_TEMPLATE_ASSERT(( has_xxx2<c2, int, int> ));
HAS_XXX_TEMPLATE_ASSERT(( has_yyy1<c4, int> ));
HAS_XXX_TEMPLATE_ASSERT(( has_yyy2<c5, int, int> ));
}

View File

@ -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"