]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
11fdf7f2 TL |
14 | #include <boost/type_erasure/detail/member11.hpp> |
15 | ||
16 | #ifndef BOOST_TYPE_ERASURE_MEMBER | |
17 | ||
7c673cae FG |
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 | ||
11fdf7f2 TL |
81 | #ifdef BOOST_TYPE_ERASURE_DOXYGEN |
82 | ||
7c673cae FG |
83 | /** |
84 | * \brief Defines a primitive concept for a member function. | |
85 | * | |
11fdf7f2 TL |
86 | * \param concept_name is the name of the concept to declare. |
87 | * If it is omitted it defaults to <code>has_ ## member</code> | |
7c673cae | 88 | * \param member is the name of the member function. |
7c673cae FG |
89 | * |
90 | * The declaration of the concept is | |
91 | * \code | |
92 | * template<class Sig, class T = _self> | |
11fdf7f2 TL |
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 | * }; | |
7c673cae | 121 | * \endcode |
7c673cae | 122 | * |
11fdf7f2 TL |
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 | |
7c673cae FG |
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 | * | |
11fdf7f2 | 137 | * For backwards compatibility, this form is always accepted. |
7c673cae | 138 | */ |
11fdf7f2 TL |
139 | #define BOOST_TYPE_ERASURE_MEMBER(concept_name, member) /**/ |
140 | ||
141 | #else | |
142 | ||
7c673cae FG |
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 | ||
11fdf7f2 TL |
150 | #endif |
151 | ||
7c673cae FG |
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... | |
11fdf7f2 TL |
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 | |
7c673cae | 167 | #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X... |
7c673cae FG |
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 | |
11fdf7f2 TL |
288 | |
289 | #endif |