1 // Boost.TypeErasure library
2 //
3 // Copyright 2012-2013 Steven Watanabe
4 //
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)
8 //
9 // $Id$
10 
11 #ifndef BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED
13 
14 #include <boost/type_erasure/detail/member11.hpp>
15 
16 #ifndef BOOST_TYPE_ERASURE_MEMBER
17 
18 #include <boost/detail/workaround.hpp>
19 #include <boost/preprocessor/cat.hpp>
20 #include <boost/preprocessor/dec.hpp>
21 #include <boost/preprocessor/comma_if.hpp>
22 #include <boost/preprocessor/repetition/enum.hpp>
23 #include <boost/preprocessor/repetition/enum_trailing.hpp>
24 #include <boost/preprocessor/repetition/enum_params.hpp>
25 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
26 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
27 #include <boost/preprocessor/seq/size.hpp>
28 #include <boost/preprocessor/seq/elem.hpp>
29 #include <boost/preprocessor/tuple/elem.hpp>
30 #include <boost/type_erasure/detail/macro.hpp>
31 #include <boost/type_erasure/detail/const.hpp>
32 #include <boost/type_erasure/rebind_any.hpp>
33 #include <boost/type_erasure/placeholder.hpp>
34 #include <boost/type_erasure/call.hpp>
35 #include <boost/type_erasure/concept_interface.hpp>
36 
37 /** INTERNAL ONLY */
38 #define BOOST_TYPE_ERASURE_MEMBER_ARG(z, n, data)  \
39     typename ::boost::type_erasure::as_param<Base, BOOST_PP_CAT(A, n)>::type BOOST_PP_CAT(a, n)
40 
41 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
42     defined(BOOST_TYPE_ERASURE_DOXYGEN) || \
43     BOOST_WORKAROUND(BOOST_MSVC, == 1800)
44 
45 /** INTERNAL ONLY */
46 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
47     BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(BOOST_PP_ENUM_PARAMS(N, A)), T>
48 
49 /** INTERNAL ONLY */
50 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
51 /** INTERNAL ONLY */
52 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) BOOST_PP_ENUM_PARAMS(N, X)
53 
54 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
55 
56 /** INTERNAL ONLY */
57 #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))
58 /** INTERNAL ONLY */
59 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_FORWARD, (X, x))
60 /** INTERNAL ONLY*/
61 #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))
62 /** INTERNAL ONLY*/
63 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_REBIND1, ~)
64 
65 #else
66 
67 /** INTERNAL ONLY */
68 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) BOOST_PP_ENUM_PARAMS(N, x)
69 /** INTERNAL ONLY*/
70 #define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) BOOST_PP_ENUM_TRAILING_PARAMS(N, a)
71 
72 #endif
73 
74 /** INTERNAL ONLY */
75 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) BOOST_PP_ENUM_TRAILING_PARAMS(N, X)
76 /** INTERNAL ONLY */
77 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, X, x)
78 /** INTERNAL ONLY */
79 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~)
80 
81 #ifdef BOOST_TYPE_ERASURE_DOXYGEN
82 
83 /**
84  * \brief Defines a primitive concept for a member function.
85  *
86  * \param concept_name is the name of the concept to declare.
87  *        If it is omitted it defaults to <code>has_ ## member</code>
88  * \param member is the name of the member function.
89  *
90  * The declaration of the concept is
91  * \code
92  * template<class Sig, class T = _self>
93  * struct concept_name;
94  * \endcode
95  * where @c Sig is a function type giving the
96  * signature of the member function, and @c T is the
97  * object type.  @c T may be const-qualified for
98  * const member functions.  @c concept_name<R(A...) const, T>
99  * is an alias for @c concept_name<R(A...), const T>.
100  *
101  * This macro can only be used at namespace scope.
102  *
103  * Example:
104  *
105  * \code
106  * namespace boost {
107  * BOOST_TYPE_ERASURE_MEMBER(push_back)
108  * }
109  * typedef boost::has_push_back<void(int)> push_back_concept;
110  * \endcode
111  *
112  * The concept defined by this function may be specialized to
113  * provide a concept_map.  The class object will be passed by
114  * reference as the first parameter.
115  *
116  * \code
117  * template<>
118  * struct has_push_back<void(int), std::list<int> > {
119  *   static void apply(std::list<int>& l, int i) { l.push_back(i); }
120  * };
121  * \endcode
122  *
123  * In C++03, the macro can only be used in the global namespace and
124  * is defined as:
125  *
126  * \code
127  * #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N)
128  * \endcode
129  *
130  * Example:
131  *
132  * \code
133  * BOOST_TYPE_ERASURE_MEMBER((boost)(has_push_back), push_back, 1)
134  * typedef boost::has_push_back<void(int), _self> push_back_concept;
135  * \endcode
136  *
137  * For backwards compatibility, this form is always accepted.
138  */
139 #define BOOST_TYPE_ERASURE_MEMBER(concept_name, member) /**/
140 
141 #else
142 
143 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N)                                \
144     BOOST_TYPE_ERASURE_MEMBER_I(                                                            \
145         qualified_name,                                                                     \
146         BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
147         member,                                                                             \
148         N)
149 
150 #endif
151 
152 #else
153 
154 /** INTERNAL ONLY */
155 #define BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(seq, N) \
156     BOOST_TYPE_ERASURE_QUALIFIED_NAME(seq)<R(A...), T>
157 
158 #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A
159 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X...
160 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
161 #   define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)...
162 #   define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::type>(a)...
163 #else
164 #   define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) x...
165 #   define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , a...
166 #endif
167 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X...
168 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x
169 #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param<Base, A>::type... a
170 
171 
172 #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, ...)                              \
173     BOOST_TYPE_ERASURE_MEMBER_I(                                                            \
174         qualified_name,                                                                     \
175         BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \
176         member,                                                                             \
177         N)
178 
179 #endif
180 
181 /** INTERNAL ONLY */
182 #define BOOST_TYPE_ERASURE_MEMBER_II(qual_name, concept_name, member, N)                        \
183     BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name)                                                \
184     template<class Sig, class T = ::boost::type_erasure::_self>                                 \
185     struct concept_name;                                                                        \
186     template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T>               \
187     struct concept_name<R(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> {                    \
188         static R apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a))     \
189         { return t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); }                 \
190     };                                                                                          \
191     template<class T BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A)>                        \
192     struct concept_name<void(BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, A)), T> {                 \
193         static void apply(T& t BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, A, a))  \
194         { t.member(BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, A, a)); }                        \
195     };                                                                                          \
196     BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qual_name)                                               \
197     namespace boost {                                                                           \
198     namespace type_erasure {                                                                    \
199     template<                                                                                   \
200         class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A),                             \
201         class T, class Base, class Enable>                                                      \
202     struct concept_interface<                                                                   \
203         BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N),                                   \
204         Base,                                                                                   \
205         typename ::boost::enable_if<                                                            \
206             ::boost::type_erasure::detail::should_be_non_const<T, Base>,                        \
207             typename ::boost::remove_const<T>::type                                             \
208         >::type,                                                                                \
209         Enable                                                                                  \
210     > : Base                                                                                    \
211     {                                                                                           \
212         typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member);                      \
213         typename rebind_any<Base, R>::type member(                                              \
214             BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N))                                             \
215         {                                                                                       \
216             return ::boost::type_erasure::call(                                                 \
217                 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(),                         \
218                 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N));                             \
219         }                                                                                       \
220     };                                                                                          \
221     template<                                                                                   \
222         class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A),                             \
223         class T, class Base, class Enable>                                                      \
224     struct concept_interface<                                                                   \
225         BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N),                                   \
226         Base,                                                                                   \
227         typename ::boost::enable_if<                                                            \
228             ::boost::type_erasure::detail::should_be_const<T, Base>,                            \
229             typename ::boost::remove_const<T>::type                                             \
230         >::type,                                                                                \
231         Enable                                                                                  \
232     > : Base                                                                                    \
233     {                                                                                           \
234         typedef void BOOST_PP_CAT(_boost_type_erasure_has_member, member);                      \
235         typename rebind_any<Base, R>::type member(                                              \
236             BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const                                       \
237         {                                                                                       \
238             return ::boost::type_erasure::call(                                                 \
239                 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(),                         \
240                 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N));                             \
241         }                                                                                       \
242     };                                                                                          \
243     template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base>   \
244     struct concept_interface<                                                                   \
245         BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N),                                   \
246         Base,                                                                                   \
247         typename ::boost::enable_if<                                                            \
248             ::boost::type_erasure::detail::should_be_non_const<T, Base>,                        \
249             typename ::boost::remove_const<T>::type                                             \
250         >::type,                                                                                \
251         typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base             \
252     {                                                                                           \
253         using Base::member;                                                                     \
254         typename rebind_any<Base, R>::type member(                                              \
255             BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N))                                             \
256         {                                                                                       \
257             return ::boost::type_erasure::call(                                                 \
258                 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(),                         \
259                 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N));                             \
260         }                                                                                       \
261     };                                                                                          \
262     template<class R BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, class A), class T, class Base>   \
263     struct concept_interface<                                                                   \
264         BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N),                                   \
265         Base,                                                                                   \
266         typename ::boost::enable_if<                                                            \
267             ::boost::type_erasure::detail::should_be_const<T, Base>,                            \
268             typename ::boost::remove_const<T>::type                                             \
269         >::type,                                                                                \
270         typename Base::BOOST_PP_CAT(_boost_type_erasure_has_member, member)> : Base             \
271     {                                                                                           \
272         using Base::member;                                                                     \
273         typename rebind_any<Base, R>::type member(                                              \
274             BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N)) const                                       \
275         {                                                                                       \
276             return ::boost::type_erasure::call(                                                 \
277                 BOOST_TYPE_ERASURE_MEMBER_QUALIFIED_ID(qual_name, N)(),                         \
278                 *this BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N));                             \
279         }                                                                                       \
280     };                                                                                          \
281     }}
282 
283 /** INTERNAL ONLY */
284 #define BOOST_TYPE_ERASURE_MEMBER_I(namespace_name, concept_name, member, N)\
285     BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N)
286 
287 #endif
288 
289 #endif
290