1 // Boost.TypeErasure library
3 // Copyright 2012-2013 Steven Watanabe
5 // Distributed under the Boost Software License Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED
14 #include <boost/preprocessor/cat.hpp>
15 #include <boost/preprocessor/dec.hpp>
16 #include <boost/preprocessor/comma_if.hpp>
17 #include <boost/preprocessor/repetition/enum.hpp>
18 #include <boost/preprocessor/repetition/enum_trailing.hpp>
19 #include <boost/preprocessor/repetition/enum_params.hpp>
20 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
21 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
22 #include <boost/preprocessor/seq/size.hpp>
23 #include <boost/preprocessor/seq/elem.hpp>
24 #include <boost/preprocessor/tuple/elem.hpp>
25 #include <boost/type_erasure/detail/macro.hpp>
26 #include <boost/type_erasure/detail/const.hpp>
27 #include <boost/type_erasure/rebind_any.hpp>
28 #include <boost/type_erasure/placeholder.hpp>
29 #include <boost/type_erasure/call.hpp>
30 #include <boost/type_erasure/concept_interface.hpp>
33 #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \
34 typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type BOOST_PP_CAT(a, n)
36 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_TYPE_ERASURE_DOXYGEN)
39 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
40 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, A)), T>
43 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
45 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X)
47 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
50 #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))
52 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x))
54 #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))
56 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~)
61 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x)
63 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a)
68 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
70 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x)
72 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~)
75 * \brief Defines a primitive concept for a member function.
77 * \param qualified_name should be a preprocessor sequence
78 * of the form (namespace1)(namespace2)...(concept_name).
79 * \param member is the name of the member function.
80 * \param N is the number of arguments of the function.
82 * The declaration of the concept is
84 * template<class Sig, class T = _self>
85 * struct ::namespace1::namespace2::...::concept_name;
87 * where Sig is a function type giving the
88 * signature of the member function, and T is the
89 * object type. T may be const-qualified for
90 * const member functions.
92 * This macro can only be used in the global namespace.
97 * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1)
98 * typedef boost::has_push_back<void(int), _self> push_back_concept;
101 * \note In C++11 the argument N is ignored and may be omitted.
102 * BOOST_TYPE_ERASURE_MEMBER will always define a variadic concept.
104 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \
105 BOOST_TYPE_ERASURE_MEMBER_I( \
107 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
114 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
115 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(A...), T>
117 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A
118 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X...
119 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)...
120 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X...
121 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::type>(a)...
122 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x
123 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param<Base, A>::type... a
126 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...) \
127 BOOST_TYPE_ERASURE_MEMBER_I( \
129 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
136 #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N) \
137 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
138 template<class Sig, class T = ::boost::type_erasure::_self> \
139 struct concept_name; \
140 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T> \
141 struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \
142 static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \
143 { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \
145 template<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)> \
146 struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \
147 static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \
148 { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \
150 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
152 namespace type_erasure { \
154 class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \
155 class T, class Base, class Enable> \
156 struct concept_interface< \
157 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
159 typename ::boost::enable_if< \
160 ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
161 typename ::boost::remove_const<T>::type \
166 typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
167 typename rebind_any<Base, R>::type member( \
168 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \
170 return ::boost::type_erasure::call( \
171 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
172 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
176 class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \
177 class T, class Base, class Enable> \
178 struct concept_interface< \
179 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
181 typename ::boost::enable_if< \
182 ::boost::type_erasure::detail::should_be_const<T, Base>, \
183 typename ::boost::remove_const<T>::type \
188 typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
189 typename rebind_any<Base, R>::type member( \
190 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \
192 return ::boost::type_erasure::call( \
193 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
194 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
197 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \
198 struct concept_interface< \
199 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
201 typename ::boost::enable_if< \
202 ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
203 typename ::boost::remove_const<T>::type \
205 typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
207 using Base::member; \
208 typename rebind_any<Base, R>::type member( \
209 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \
211 return ::boost::type_erasure::call( \
212 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
213 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
216 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \
217 struct concept_interface< \
218 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
220 typename ::boost::enable_if< \
221 ::boost::type_erasure::detail::should_be_const<T, Base>, \
222 typename ::boost::remove_const<T>::type \
224 typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
226 using Base::member; \
227 typename rebind_any<Base, R>::type member( \
228 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \
230 return ::boost::type_erasure::call( \
231 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
232 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
238 #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\
239 BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N)