diff options
Diffstat (limited to 'boost/type_erasure/member.hpp')
-rw-r--r-- | boost/type_erasure/member.hpp | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/boost/type_erasure/member.hpp b/boost/type_erasure/member.hpp new file mode 100644 index 0000000000..a6de24ab8e --- /dev/null +++ b/boost/type_erasure/member.hpp @@ -0,0 +1,241 @@ +// 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 <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/dec.hpp> +#include <boost/preprocessor/comma_if.hpp> +#include <boost/preprocessor/repetition/enum.hpp> +#include <boost/preprocessor/repetition/enum_trailing.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +#include <boost/preprocessor/seq/size.hpp> +#include <boost/preprocessor/seq/elem.hpp> +#include <boost/preprocessor/tuple/elem.hpp> +#include <boost/type_erasure/detail/macro.hpp> +#include <boost/type_erasure/detail/const.hpp> +#include <boost/type_erasure/rebind_any.hpp> +#include <boost/type_erasure/placeholder.hpp> +#include <boost/type_erasure/call.hpp> +#include <boost/type_erasure/concept_interface.hpp> + +/** INTERNAL ONLY */ +#define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \ + typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::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)<R(BOOST_PP_ENUM_PARAMS(N, A)), T> + +/** 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, 0, data), n)>(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<typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::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<class Sig, class T = _self> + * 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<void(int), _self> 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)<R(A...), T> + +#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>(x)... +#define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X... +#define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::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<Base, A>::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<class Sig, class T = ::boost::type_erasure::_self> \ + struct concept_name; \ + template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T> \ + struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \ + 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<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)> \ + struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \ + 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<T, Base>, \ + typename ::boost::remove_const<T>::type \ + >::type, \ + Enable \ + > : Base \ + { \ + typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ + typename rebind_any<Base, R>::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<T, Base>, \ + typename ::boost::remove_const<T>::type \ + >::type, \ + Enable \ + > : Base \ + { \ + typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \ + typename rebind_any<Base, R>::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<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \ + 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<T, Base>, \ + typename ::boost::remove_const<T>::type \ + >::type, \ + typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ + { \ + using Base::member; \ + typename rebind_any<Base, R>::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> \ + struct concept_interface< \ + BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \ + Base, \ + typename ::boost::enable_if< \ + ::boost::type_erasure::detail::should_be_const<T, Base>, \ + typename ::boost::remove_const<T>::type \ + >::type, \ + typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \ + { \ + using Base::member; \ + typename rebind_any<Base, R>::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 |