Hello,
I've attached a rewrite of the patch I previously submitted that
includes documentation and new tests in MPL's test suite. Apply with
'patch -p0 < djw_has_xxx_template.patch' from the boost root
directory.
This implementation is based on comp.lang.c++.moderated USENET
postings from Rani Sharoni (2002-03-17,
http://tinyurl.com/2u2a9f) and
Aleksey Gurtovoy (2002-03-19,
http://tinyurl.com/376y7c), the current
has_xxx implementation (especially ideas in the msvc 8.0
implementation from Daniel Wallin, I believe), the 3rd code example in
section 14.2.8 of the standard, and the discussion on this thread
(especially postings from Guillaume Melquiond who pointed out to me
the need for a seperate "substitute" template). Also, thanks to
Aleksey Gurtovoy and David Abrahams for implementing has_xxx in the
first place and especially for including citations of the USENET
discussions in has_xxx.hpp. They were invaluable.
By testing combinations of different members, member names, member
types, and member template arities, I have 142 individual tests (i.e.
assertions) for detecting member templates. Here is the pass/fail rate
for the compilers I tested.
gcc 3.4, 4.0, 4.1 - 142/142
gcc 3.3 - 139/142
msvc 7.1, 8.0: 142/142
comeau 4.3.8 alpha online: 93/142 (I had to run it through the
preprocessor and then paste it on the website's form)
The tests that fail on gcc 3.3 are for rejecting member templates with
the correct name but incorrect number of parameters. Comeau also
cannot do this and additionally cannot reject members with the correct
name that aren't templates (typedefs and structs) and cannot detect
member templates with the correct name but no required parameters (all
parameters have defaults).
Other changes from my previous patch include:
1) changed the name of BOOST_MPL_HAS_TEMPLATE_XXX_TRAIT_DEF to
BOOST_MPL_HAS_XXX_TEMPLATE_DEF, same for NAMED_DEF version. It's more
concise. Also, by default the name of the generated metafunction is a
concatination of 'has_' and the name of the nested template rather
than 'has_template_' and the name of the nested template. This is also
done for brievity's sake.
2) included the macro definitions in has_xxx.hpp rather than creating
new files. These are closely related, and at some point in the future
the implementations for has_xxx for nested types and has_xxx for
nested templates could be folded together to improve code reuse.
3) created the following new documentation files
- libs/mpl/doc/src/refmanual/CFG_NO_HAS_TEMPLATE_XXX.rst
- libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_DEF.rst
- libs/mpl/doc/src/refmanual/HAS_XXX_TEMPLATE_NAMED_DEF.rst
I wasn't sure how to generate the HTML and pdf manuals.
4) added the tests to has_xxx.cpp and no_has_xxx.cpp
I'm assuming this is too late to be considered for 1.34, so I built
the patch off the cvs trunk rather than RC_1_34_0. I replaced my
previous patch on SF patch tracker with the current one.
As for future work:
1) Though the two most common compilers, gcc 4 and msvc 7.1/8.0, pass
all the tests, it would be nice to have work arounds so that all
compilers pass all the tests.
2) I believe this can be extended along the lines of John Madsen's
comp.lang.c++.moderated posting (1999-11-12,
http://tinyurl.com/2wqorl) to test for other sorts of members by
creating new substitute templates for SFINAE. I made an initial try at
detecting member data and had some success. If there's interest I
could look into extending has_xxx for member templates into a more
complete set of compile time type introspection metafunctions...
something like has_member_data, has_member_function, has_member_type,
has_member_template. The last two metafunction would supersede the
currect has_xxx and my has_xxx for templates.
Let me know if you have trouble applying the patch or if you have
suggests to improve this.
Thanks!
Daniel
P.S.
The example of using BOOST_MPL_HAS_XXX_TEMPLATE_DEF that I posted with
my original patch should now look like the following (if you want to
copy and past it for a quick test).
#include <utility>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/utility/result_of.hpp>
// Create has_result to detect nested members like
// template<class T> struct result {}.
// The first macro argument is the member name and the second argument
// is the number of template parameters.
BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result, 1)
struct pair_maker {
template<typename F> struct result;
template<typename F, typename Arg0, typename Arg1>
struct result<F(Arg0, Arg1)> {
typedef std::pair<Arg0, Arg1> type;
};
template<typename Arg0, typename Arg1>
typename result<pair_maker(Arg0, Arg1)>::type
operator()(Arg0 a0, Arg1 a1) const
{
return std::make_pair(a0, a1);
}
};
int main()
{
using namespace boost;
typedef char value_type;
BOOST_MPL_ASSERT((
has_result<
pair_maker,
pair_maker(value_type, value_type)
>
));
typedef result_of<
pair_maker(value_type, value_type)
>::type result_type;
value_type x, y;
pair_maker f;
result_type result = f(x, y);
}
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 <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 !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<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 the 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|
+
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<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 the 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|
+
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/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 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<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_ASSERT(( has_xxx<b6,true_> ));
MPL_ASSERT(( has_xxx<b7,true_> ));
+#if !BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4308))
+ 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 @@
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))
+ 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> ));
}
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"
_______________________________________________
Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost