// Boost.TypeErasure library // // Copyright 2012-2013 Steven Watanabe // // 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) // // $Id$ #ifndef BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED #define BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \ typename ::boost::type_erasure::as_param::type BOOST_PP_CAT(a, n) #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_TYPE_ERASURE_DOXYGEN) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \ BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X) #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_FORWARD(z, n, data) ::std::forward(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 1, data), n)) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x)) /** INTERNAL ONLY*/ #define BOOST_TYPE_ERASURE_FORWARD_REBIND1(z, n, data) ::std::forward::type>(BOOST_PP_CAT(a, n)) /** INTERNAL ONLY*/ #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~) #else /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x) /** INTERNAL ONLY*/ #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a) #endif /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x) /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~) /** * \brief Defines a primitive concept for a member function. * * \param qualified_name should be a preprocessor sequence * of the form (namespace1)(namespace2)...(concept_name). * \param member is the name of the member function. * \param N is the number of arguments of the function. * * The declaration of the concept is * \code * template * struct ::namespace1::namespace2::...::concept_name; * \endcode * where Sig is a function type giving the * signature of the member function, and T is the * object type. T may be const-qualified for * const member functions. * * This macro can only be used in the global namespace. * * Example: * * \code * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1) * typedef boost::has_push_back push_back_concept; * \endcode * * \note In C++11 the argument N is ignored and may be omitted. * BOOST_TYPE_ERASURE_MEMBER will always define a variadic concept. */ #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \ BOOST_TYPE_ERASURE_MEMBER_I( \ qualified_name, \ BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ member, \ N) #else /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \ BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq) #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X... #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward(x)... #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X... #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward::type>(a)... #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param::type... a #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...) \ BOOST_TYPE_ERASURE_MEMBER_I( \ qualified_name, \ BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ member, \ N) #endif /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N) \ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \ template \ struct concept_name; \ template \ struct concept_name { \ static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \ { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \ }; \ template \ struct concept_name { \ static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \ { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \ }; \ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \ namespace boost { \ namespace type_erasure { \ template< \ class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \ class T, class Base, class Enable> \ struct concept_interface< \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ Base, \ typename ::boost::enable_if< \ ::boost::type_erasure::detail::should_be_non_const, \ typename ::boost::remove_const::type \ >::type, \ Enable \ > : Base \ { \ typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ typename rebind_any::type member( \ BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \ { \ return ::boost::type_erasure::call( \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ } \ }; \ template< \ class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \ class T, class Base, class Enable> \ struct concept_interface< \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ Base, \ typename ::boost::enable_if< \ ::boost::type_erasure::detail::should_be_const, \ typename ::boost::remove_const::type \ >::type, \ Enable \ > : Base \ { \ typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ typename rebind_any::type member( \ BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \ { \ return ::boost::type_erasure::call( \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ } \ }; \ template \ struct concept_interface< \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ Base, \ typename ::boost::enable_if< \ ::boost::type_erasure::detail::should_be_non_const, \ typename ::boost::remove_const::type \ >::type, \ typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ { \ using Base::member; \ typename rebind_any::type member( \ BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \ { \ return ::boost::type_erasure::call( \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ } \ }; \ template \ struct concept_interface< \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ Base, \ typename ::boost::enable_if< \ ::boost::type_erasure::detail::should_be_const, \ typename ::boost::remove_const::type \ >::type, \ typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ { \ using Base::member; \ typename rebind_any::type member( \ BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \ { \ return ::boost::type_erasure::call( \ BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \ *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \ } \ }; \ }} /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\ BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N) #endif