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/detail/workaround.hpp>
15 #include <boost/preprocessor/cat.hpp>
16 #include <boost/preprocessor/dec.hpp>
17 #include <boost/preprocessor/comma_if.hpp>
18 #include <boost/preprocessor/repetition/enum.hpp>
19 #include <boost/preprocessor/repetition/enum_trailing.hpp>
20 #include <boost/preprocessor/repetition/enum_params.hpp>
21 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
22 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
23 #include <boost/preprocessor/seq/size.hpp>
24 #include <boost/preprocessor/seq/elem.hpp>
25 #include <boost/preprocessor/tuple/elem.hpp>
26 #include <boost/type_erasure/detail/macro.hpp>
27 #include <boost/type_erasure/detail/const.hpp>
28 #include <boost/type_erasure/rebind_any.hpp>
29 #include <boost/type_erasure/placeholder.hpp>
30 #include <boost/type_erasure/call.hpp>
31 #include <boost/type_erasure/concept_interface.hpp>
34 #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data) \
35 typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type BOOST_PP_CAT(a, n)
37 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
38 defined(BOOST_TYPE_ERASURE_DOXYGEN) || \
39 BOOST_WORKAROUND(BOOST_MSVC, == 1800)
42 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
43 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, A)), T>
46 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
48 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X)
50 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
53 #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))
55 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x))
57 #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))
59 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~)
64 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x)
66 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a)
71 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
73 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x)
75 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~)
78 * \brief Defines a primitive concept for a member function.
80 * \param qualified_name should be a preprocessor sequence
81 * of the form (namespace1)(namespace2)...(concept_name).
82 * \param member is the name of the member function.
83 * \param N is the number of arguments of the function.
85 * The declaration of the concept is
87 * template<class Sig, class T = _self>
88 * struct ::namespace1::namespace2::...::concept_name;
90 * where Sig is a function type giving the
91 * signature of the member function, and T is the
92 * object type. T may be const-qualified for
93 * const member functions.
95 * This macro can only be used in the global namespace.
100 * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1)
101 * typedef boost::has_push_back<void(int), _self> push_back_concept;
104 * \note In C++11 the argument N is ignored and may be omitted.
105 * BOOST_TYPE_ERASURE_MEMBER will always define a variadic concept.
107 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \
108 BOOST_TYPE_ERASURE_MEMBER_I( \
110 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
117 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
118 BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(A...), T>
120 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A
121 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X...
122 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)...
123 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X...
124 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::type>(a)...
125 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x
126 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param<Base, A>::type... a
129 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...) \
130 BOOST_TYPE_ERASURE_MEMBER_I( \
132 BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
139 #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N) \
140 BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \
141 template<class Sig, class T = ::boost::type_erasure::_self> \
142 struct concept_name; \
143 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T> \
144 struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \
145 static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \
146 { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \
148 template<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)> \
149 struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> { \
150 static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a)) \
151 { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); } \
153 BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name) \
155 namespace type_erasure { \
157 class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \
158 class T, class Base, class Enable> \
159 struct concept_interface< \
160 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
162 typename ::boost::enable_if< \
163 ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
164 typename ::boost::remove_const<T>::type \
169 typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
170 typename rebind_any<Base, R>::type member( \
171 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \
173 return ::boost::type_erasure::call( \
174 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
175 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
179 class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), \
180 class T, class Base, class Enable> \
181 struct concept_interface< \
182 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
184 typename ::boost::enable_if< \
185 ::boost::type_erasure::detail::should_be_const<T, Base>, \
186 typename ::boost::remove_const<T>::type \
191 typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member); \
192 typename rebind_any<Base, R>::type member( \
193 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \
195 return ::boost::type_erasure::call( \
196 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
197 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
200 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \
201 struct concept_interface< \
202 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
204 typename ::boost::enable_if< \
205 ::boost::type_erasure::detail::should_be_non_const<T, Base>, \
206 typename ::boost::remove_const<T>::type \
208 typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
210 using Base::member; \
211 typename rebind_any<Base, R>::type member( \
212 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) \
214 return ::boost::type_erasure::call( \
215 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
216 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
219 template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base> \
220 struct concept_interface< \
221 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N), \
223 typename ::boost::enable_if< \
224 ::boost::type_erasure::detail::should_be_const<T, Base>, \
225 typename ::boost::remove_const<T>::type \
227 typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base \
229 using Base::member; \
230 typename rebind_any<Base, R>::type member( \
231 BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const \
233 return ::boost::type_erasure::call( \
234 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(), \
235 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N)); \
241 #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\
242 BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N)