]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.TypeErasure library |
2 | // | |
3 | // Copyright 2011 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 | #if !defined(BOOST_PP_IS_ITERATING) | |
12 | ||
13 | #ifndef BOOST_TYPE_ERASURE_CALL_HPP_INCLUDED | |
14 | #define BOOST_TYPE_ERASURE_CALL_HPP_INCLUDED | |
15 | ||
16 | #include <boost/assert.hpp> | |
17 | #include <boost/mpl/bool.hpp> | |
18 | #include <boost/mpl/eval_if.hpp> | |
19 | #include <boost/mpl/identity.hpp> | |
20 | #include <boost/type_traits/remove_cv.hpp> | |
21 | #include <boost/type_traits/remove_reference.hpp> | |
22 | #include <boost/preprocessor/cat.hpp> | |
23 | #include <boost/preprocessor/inc.hpp> | |
24 | #include <boost/preprocessor/iteration/iterate.hpp> | |
25 | #include <boost/preprocessor/repetition/repeat.hpp> | |
26 | #include <boost/preprocessor/repetition/enum.hpp> | |
27 | #include <boost/preprocessor/repetition/enum_trailing.hpp> | |
28 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
29 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> | |
30 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> | |
31 | #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> | |
32 | #include <boost/type_erasure/detail/access.hpp> | |
33 | #include <boost/type_erasure/detail/adapt_to_vtable.hpp> | |
34 | #include <boost/type_erasure/detail/extract_concept.hpp> | |
35 | #include <boost/type_erasure/detail/get_signature.hpp> | |
36 | #include <boost/type_erasure/detail/check_call.hpp> | |
37 | #include <boost/type_erasure/is_placeholder.hpp> | |
38 | #include <boost/type_erasure/concept_of.hpp> | |
39 | #include <boost/type_erasure/config.hpp> | |
40 | #include <boost/type_erasure/require_match.hpp> | |
41 | ||
42 | namespace boost { | |
43 | namespace type_erasure { | |
44 | ||
45 | template<class Concept, class Placeholder> | |
46 | class any; | |
47 | ||
48 | template<class Concept> | |
49 | class binding; | |
50 | ||
51 | namespace detail { | |
52 | ||
53 | template<class T> | |
54 | struct is_placeholder_arg : | |
55 | ::boost::type_erasure::is_placeholder< | |
56 | typename ::boost::remove_cv< | |
57 | typename ::boost::remove_reference<T>::type | |
58 | >::type | |
59 | > | |
60 | {}; | |
61 | ||
62 | template<class T, class Table> | |
63 | int maybe_get_table(const T& arg, const Table*& table, boost::mpl::true_) | |
64 | { | |
65 | if(table == 0) { | |
66 | table = &::boost::type_erasure::detail::access::table(arg); | |
67 | } | |
68 | return 0; | |
69 | } | |
70 | ||
71 | template<class T, class Table> | |
72 | int maybe_get_table(const T&, const Table*&, boost::mpl::false_) { return 0; } | |
73 | ||
74 | template<class T> | |
75 | ::boost::type_erasure::detail::storage& convert_arg(any_base<T>& arg, boost::mpl::true_) | |
76 | { | |
77 | return ::boost::type_erasure::detail::access::data(arg); | |
78 | } | |
79 | ||
80 | template<class Concept, class T> | |
81 | const ::boost::type_erasure::detail::storage& | |
82 | convert_arg(any_base<any<Concept, const T&> >& arg, boost::mpl::true_) | |
83 | { | |
84 | return ::boost::type_erasure::detail::access::data(arg); | |
85 | } | |
86 | ||
87 | template<class T> | |
88 | const ::boost::type_erasure::detail::storage& | |
89 | convert_arg(const any_base<T>& arg, boost::mpl::true_) | |
90 | { | |
91 | return ::boost::type_erasure::detail::access::data(arg); | |
92 | } | |
93 | ||
94 | template<class Concept, class T> | |
95 | ::boost::type_erasure::detail::storage& | |
96 | convert_arg(const any_base<any<Concept, T&> >& arg, boost::mpl::true_) | |
97 | { | |
98 | return ::boost::type_erasure::detail::access::data(arg); | |
99 | } | |
100 | ||
101 | template<class Concept, class T> | |
102 | const ::boost::type_erasure::detail::storage& | |
103 | convert_arg(const any_base<any<Concept, const T&> >& arg, boost::mpl::true_) | |
104 | { | |
105 | return ::boost::type_erasure::detail::access::data(arg); | |
106 | } | |
107 | ||
108 | template<class Concept, class T> | |
109 | ::boost::type_erasure::detail::storage& | |
110 | convert_arg(param<Concept, T>& arg, boost::mpl::true_) | |
111 | { | |
112 | return ::boost::type_erasure::detail::access::data(arg); | |
113 | } | |
114 | ||
115 | template<class Concept, class T> | |
116 | const ::boost::type_erasure::detail::storage& | |
117 | convert_arg(param<Concept, const T&>& arg, boost::mpl::true_) | |
118 | { | |
119 | return ::boost::type_erasure::detail::access::data(arg); | |
120 | } | |
121 | ||
122 | template<class Concept, class T> | |
123 | const ::boost::type_erasure::detail::storage& | |
124 | convert_arg(const param<Concept, T>& arg, boost::mpl::true_) | |
125 | { | |
126 | return ::boost::type_erasure::detail::access::data(arg); | |
127 | } | |
128 | ||
129 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
130 | ||
131 | template<class Concept, class T> | |
132 | const ::boost::type_erasure::detail::storage& | |
133 | convert_arg(any_base<any<Concept, const T&> >&& arg, boost::mpl::true_) | |
134 | { | |
135 | return ::boost::type_erasure::detail::access::data(arg); | |
136 | } | |
137 | ||
138 | template<class Concept, class T> | |
139 | ::boost::type_erasure::detail::storage& | |
140 | convert_arg(any_base<any<Concept, T&> >&& arg, boost::mpl::true_) | |
141 | { | |
142 | return ::boost::type_erasure::detail::access::data(arg); | |
143 | } | |
144 | ||
145 | template<class Concept, class T> | |
146 | ::boost::type_erasure::detail::storage&& | |
147 | convert_arg(any_base<any<Concept, T> >&& arg, boost::mpl::true_) | |
148 | { | |
149 | return ::boost::type_erasure::detail::access::data(std::move(arg)); | |
150 | } | |
151 | ||
152 | template<class Concept, class T> | |
153 | ::boost::type_erasure::detail::storage&& | |
154 | convert_arg(any_base<any<Concept, T&&> >& arg, boost::mpl::true_) | |
155 | { | |
156 | return ::boost::type_erasure::detail::access::data(arg); | |
157 | } | |
158 | ||
159 | template<class Concept, class T> | |
160 | ::boost::type_erasure::detail::storage&& | |
161 | convert_arg(const any_base<any<Concept, T&&> >& arg, boost::mpl::true_) | |
162 | { | |
163 | return ::boost::type_erasure::detail::access::data(arg); | |
164 | } | |
165 | ||
166 | template<class Concept, class T> | |
167 | const ::boost::type_erasure::detail::storage& | |
168 | convert_arg(param<Concept, const T&>&& arg, boost::mpl::true_) | |
169 | { | |
170 | return ::boost::type_erasure::detail::access::data(arg); | |
171 | } | |
172 | ||
173 | template<class Concept, class T> | |
174 | ::boost::type_erasure::detail::storage& | |
175 | convert_arg(param<Concept, T&>&& arg, boost::mpl::true_) | |
176 | { | |
177 | return ::boost::type_erasure::detail::access::data(arg); | |
178 | } | |
179 | ||
180 | template<class Concept, class T> | |
181 | ::boost::type_erasure::detail::storage&& | |
182 | convert_arg(param<Concept, T>&& arg, boost::mpl::true_) | |
183 | { | |
184 | return ::boost::type_erasure::detail::access::data(std::move(arg)); | |
185 | } | |
186 | ||
187 | template<class Concept, class T> | |
188 | ::boost::type_erasure::detail::storage&& | |
189 | convert_arg(param<Concept, T&&>& arg, boost::mpl::true_) | |
190 | { | |
191 | return ::boost::type_erasure::detail::access::data(arg); | |
192 | } | |
193 | ||
194 | template<class Concept, class T> | |
195 | ::boost::type_erasure::detail::storage&& | |
196 | convert_arg(const param<Concept, T&&>& arg, boost::mpl::true_) | |
197 | { | |
198 | return ::boost::type_erasure::detail::access::data(arg); | |
199 | } | |
200 | ||
201 | template<class T> | |
202 | T&& convert_arg(T&& arg, boost::mpl::false_) { return std::forward<T>(arg); } | |
203 | ||
204 | #else | |
205 | ||
206 | template<class T> | |
207 | T& convert_arg(T& arg, boost::mpl::false_) { return arg; } | |
208 | ||
209 | #endif | |
210 | ||
211 | } | |
212 | ||
213 | #ifdef BOOST_TYPE_ERASURE_DOXYGEN | |
214 | ||
215 | /** | |
216 | * Dispatches a type erased function. | |
217 | * | |
218 | * @c Op must be a primitive concept which is present in | |
219 | * @c Concept. Its signature determines how the arguments of | |
220 | * \call are handled. If the argument is a @ref placeholder, | |
221 | * \call expects an @ref any using that @ref placeholder. | |
222 | * This @ref any is unwrapped by \call. The type that | |
223 | * it stores must be the same type specified by @c binding. | |
224 | * Any arguments that are not placeholders in the signature | |
225 | * of @c Op are passed through unchanged. | |
226 | * | |
227 | * If @c binding is not specified, it will be deduced from | |
228 | * the arguments. Naturally this requires at least one | |
229 | * argument to be an @ref any. In this case, all @ref any | |
230 | * arguments must have the same @ref binding. | |
231 | * | |
232 | * \return The result of the operation. If the result type | |
233 | * of the signature of @c Op is a placeholder, the | |
234 | * result will be converted to the appropriate @ref | |
235 | * any type. | |
236 | * | |
237 | * \throws bad_function_call if @ref relaxed is | |
238 | * in @c Concept and there is a type mismatch. | |
239 | * | |
240 | * Example: | |
241 | * | |
242 | * @code | |
243 | * typedef mpl::vector< | |
244 | * copy_constructible<_b>, | |
245 | * addable<_a, int, _b> > concept; | |
246 | * any<concept, _a> a = ...; | |
247 | * any<concept, _b> b(call(addable<_a, int, _b>(), a, 10)); | |
248 | * @endcode | |
249 | * | |
250 | * The signature of @ref addable is <code>_b(const _a&, const int&)</code> | |
251 | */ | |
252 | template<class Concept, class Op, class... U> | |
253 | typename ::boost::type_erasure::detail::call_impl<Sig, U..., Concept>::type | |
254 | call(const binding<Concept>& binding_arg, const Op&, U&&... args); | |
255 | ||
256 | /** | |
257 | * \overload | |
258 | */ | |
259 | template<class Op, class... U> | |
260 | typename ::boost::type_erasure::detail::call_impl<Sig, U...>::type | |
261 | call(const Op&, U&&... args); | |
262 | ||
263 | #else | |
264 | ||
265 | namespace detail { | |
266 | ||
267 | template<class Sig, class Args, class Concept = void, | |
268 | bool Check = ::boost::type_erasure::detail::check_call<Sig, Args>::type::value> | |
269 | struct call_impl {}; | |
270 | ||
271 | template<class Op, class Args, class Concept = void> | |
272 | struct call_result : | |
273 | call_impl< | |
274 | typename ::boost::type_erasure::detail::get_signature<Op>::type, | |
275 | Args, | |
276 | Concept> | |
277 | {}; | |
278 | ||
279 | template<class C1, class Args, class Concept> | |
280 | struct call_result< | |
281 | ::boost::type_erasure::binding<C1>, | |
282 | Args, | |
283 | Concept | |
284 | > | |
285 | {}; | |
286 | ||
287 | } | |
288 | ||
289 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
290 | ||
291 | namespace detail { | |
292 | ||
293 | template<class... T> | |
294 | void ignore(const T&...) {} | |
295 | ||
296 | template<class R, class... T, class... U> | |
297 | const ::boost::type_erasure::binding< | |
298 | typename ::boost::type_erasure::detail::extract_concept<void(T...), U...>::type>* | |
299 | extract_table(R(*)(T...), const U&... arg) | |
300 | { | |
301 | const ::boost::type_erasure::binding< | |
302 | typename ::boost::type_erasure::detail::extract_concept< | |
303 | void(T...), U...>::type>* result = 0; | |
304 | ||
305 | // the order that we run maybe_get_table in doesn't matter | |
306 | ignore(::boost::type_erasure::detail::maybe_get_table( | |
307 | arg, | |
308 | result, | |
309 | ::boost::type_erasure::detail::is_placeholder_arg<T>())...); | |
310 | ||
311 | BOOST_ASSERT(result != 0); | |
312 | return result; | |
313 | } | |
314 | ||
315 | template<class Sig, class Args, class Concept, bool ReturnsAny> | |
316 | struct call_impl_dispatch; | |
317 | ||
318 | template<class R, class... T, class... U, class Concept> | |
319 | struct call_impl_dispatch<R(T...), void(U...), Concept, false> | |
320 | { | |
321 | typedef R type; | |
322 | template<class F> | |
323 | static R apply(const ::boost::type_erasure::binding<Concept>* table, U... arg) | |
324 | { | |
325 | return table->template find<F>()( | |
326 | ::boost::type_erasure::detail::convert_arg( | |
327 | ::std::forward<U>(arg), | |
328 | ::boost::type_erasure::detail::is_placeholder_arg<T>())...); | |
329 | } | |
330 | }; | |
331 | ||
332 | template<class R, class... T, class... U, class Concept> | |
333 | struct call_impl_dispatch<R(T...), void(U...), Concept, true> | |
334 | { | |
335 | typedef ::boost::type_erasure::any<Concept, R> type; | |
336 | template<class F> | |
337 | static type apply(const ::boost::type_erasure::binding<Concept>* table, U... arg) | |
338 | { | |
339 | return type(table->template find<F>()( | |
340 | ::boost::type_erasure::detail::convert_arg( | |
341 | ::std::forward<U>(arg), | |
342 | ::boost::type_erasure::detail::is_placeholder_arg<T>())...), *table); | |
343 | } | |
344 | }; | |
345 | ||
346 | template<class R, class... T, class... U, class Concept> | |
347 | struct call_impl<R(T...), void(U...), Concept, true> : | |
348 | ::boost::type_erasure::detail::call_impl_dispatch< | |
349 | R(T...), | |
350 | void(U...), | |
351 | Concept, | |
352 | ::boost::type_erasure::detail::is_placeholder_arg<R>::value | |
353 | > | |
354 | { | |
355 | }; | |
356 | ||
357 | template<class R, class... T, class... U> | |
358 | struct call_impl<R(T...), void(U...), void, true> : | |
359 | ::boost::type_erasure::detail::call_impl_dispatch< | |
360 | R(T...), | |
361 | void(U...), | |
362 | typename ::boost::type_erasure::detail::extract_concept< | |
363 | void(T...), | |
364 | typename ::boost::remove_reference<U>::type... | |
365 | >::type, | |
366 | ::boost::type_erasure::detail::is_placeholder_arg<R>::value | |
367 | > | |
368 | { | |
369 | }; | |
370 | ||
371 | } | |
372 | ||
373 | template< | |
374 | class Concept, | |
375 | class Op, | |
376 | class... U | |
377 | > | |
378 | typename ::boost::type_erasure::detail::call_result< | |
379 | Op, | |
380 | void(U&&...), | |
381 | Concept | |
382 | >::type | |
383 | unchecked_call( | |
384 | const ::boost::type_erasure::binding<Concept>& table, | |
385 | const Op&, | |
386 | U&&... arg) | |
387 | { | |
388 | return ::boost::type_erasure::detail::call_impl< | |
389 | typename ::boost::type_erasure::detail::get_signature<Op>::type, | |
390 | void(U&&...), | |
391 | Concept | |
392 | >::template apply< | |
393 | typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type | |
394 | >(&table, std::forward<U>(arg)...); | |
395 | } | |
396 | ||
397 | template<class Concept, class Op, class... U> | |
398 | typename ::boost::type_erasure::detail::call_result< | |
399 | Op, | |
400 | void(U&&...), | |
401 | Concept | |
402 | >::type | |
403 | call( | |
404 | const ::boost::type_erasure::binding<Concept>& table, | |
405 | const Op& f, | |
406 | U&&... arg) | |
407 | { | |
408 | ::boost::type_erasure::require_match(table, f, std::forward<U>(arg)...); | |
409 | return ::boost::type_erasure::unchecked_call(table, f, std::forward<U>(arg)...); | |
410 | } | |
411 | ||
412 | template<class Op, class... U> | |
413 | typename ::boost::type_erasure::detail::call_result< | |
414 | Op, | |
415 | void(U&&...) | |
416 | >::type | |
417 | unchecked_call( | |
418 | const Op&, | |
419 | U&&... arg) | |
420 | { | |
421 | return ::boost::type_erasure::detail::call_impl< | |
422 | typename ::boost::type_erasure::detail::get_signature<Op>::type, | |
423 | void(U&&...) | |
424 | >::template apply< | |
425 | typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type | |
426 | >(::boost::type_erasure::detail::extract_table( | |
427 | static_cast<typename ::boost::type_erasure::detail::get_signature<Op>::type*>(0), arg...), | |
428 | std::forward<U>(arg)...); | |
429 | } | |
430 | ||
431 | template<class Op, class... U> | |
432 | typename ::boost::type_erasure::detail::call_result< | |
433 | Op, | |
434 | void(U&&...) | |
435 | >::type | |
436 | call( | |
437 | const Op& f, | |
438 | U&&... arg) | |
439 | { | |
440 | ::boost::type_erasure::require_match(f, std::forward<U>(arg)...); | |
441 | return ::boost::type_erasure::unchecked_call(f, std::forward<U>(arg)...); | |
442 | } | |
443 | ||
444 | ||
445 | #else | |
446 | ||
447 | #define BOOST_PP_FILENAME_1 <boost/type_erasure/call.hpp> | |
448 | #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) | |
449 | #include BOOST_PP_ITERATE() | |
450 | ||
451 | #endif | |
452 | ||
453 | #endif | |
454 | ||
455 | } | |
456 | } | |
457 | ||
458 | #endif | |
459 | ||
460 | #else | |
461 | ||
462 | #define N BOOST_PP_ITERATION() | |
463 | ||
464 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES | |
465 | ||
466 | #define BOOST_TYPE_ERASURE_CONVERT_ARG(z, n, data) \ | |
467 | ::boost::type_erasure::detail::convert_arg( \ | |
468 | std::forward<BOOST_PP_CAT(U, n)>(BOOST_PP_CAT(arg, n)), \ | |
469 | ::boost::type_erasure::detail::is_placeholder_arg<BOOST_PP_CAT(T, n)>()) | |
470 | ||
471 | #else | |
472 | ||
473 | #define BOOST_TYPE_ERASURE_CONVERT_ARG(z, n, data) \ | |
474 | ::boost::type_erasure::detail::convert_arg( \ | |
475 | BOOST_PP_CAT(arg, n), \ | |
476 | ::boost::type_erasure::detail::is_placeholder_arg<BOOST_PP_CAT(T, n)>()) | |
477 | ||
478 | #endif | |
479 | ||
480 | #define BOOST_TYPE_ERASURE_GET_TABLE(z, n, data) \ | |
481 | ::boost::type_erasure::detail::maybe_get_table( \ | |
482 | BOOST_PP_CAT(arg, n), \ | |
483 | result, \ | |
484 | ::boost::type_erasure::detail::is_placeholder_arg<BOOST_PP_CAT(T, n)>()); | |
485 | ||
486 | namespace detail { | |
487 | ||
488 | #if N != 0 | |
489 | ||
490 | template< | |
491 | class R, | |
492 | BOOST_PP_ENUM_PARAMS(N, class T), | |
493 | BOOST_PP_ENUM_PARAMS(N, class U)> | |
494 | const ::boost::type_erasure::binding< | |
495 | typename ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)< | |
496 | BOOST_PP_ENUM_PARAMS(N, T), | |
497 | BOOST_PP_ENUM_PARAMS(N, U)>::type>* | |
498 | BOOST_PP_CAT(extract_table, N)(R(*)(BOOST_PP_ENUM_PARAMS(N, T)), BOOST_PP_ENUM_BINARY_PARAMS(N, const U, &arg)) | |
499 | { | |
500 | const ::boost::type_erasure::binding< | |
501 | typename ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)< | |
502 | BOOST_PP_ENUM_PARAMS(N, T), | |
503 | BOOST_PP_ENUM_PARAMS(N, U)>::type>* result = 0; | |
504 | BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_GET_TABLE, ~) | |
505 | BOOST_ASSERT(result != 0); | |
506 | return result; | |
507 | } | |
508 | ||
509 | #endif | |
510 | ||
511 | template< | |
512 | class R | |
513 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) | |
514 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), | |
515 | class Concept | |
516 | #if N != 0 | |
517 | = typename ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)< | |
518 | BOOST_PP_ENUM_PARAMS(N, T), | |
519 | BOOST_PP_ENUM_PARAMS(N, U) | |
520 | >::type | |
521 | #endif | |
522 | , | |
523 | bool ReturnsAny = ::boost::type_erasure::detail::is_placeholder_arg<R>::value> | |
524 | struct BOOST_PP_CAT(call_impl, N); | |
525 | ||
526 | template< | |
527 | class R | |
528 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) | |
529 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), | |
530 | class Concept | |
531 | > | |
532 | struct BOOST_PP_CAT(call_impl, N)< | |
533 | R | |
534 | BOOST_PP_ENUM_TRAILING_PARAMS(N, T) | |
535 | BOOST_PP_ENUM_TRAILING_PARAMS(N, U), | |
536 | Concept, | |
537 | false | |
538 | > | |
539 | { | |
540 | typedef R type; | |
541 | template<class F> | |
542 | static R apply(const ::boost::type_erasure::binding<Concept>* table | |
543 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, arg)) | |
544 | { | |
545 | return table->template find<F>()( | |
546 | BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_CONVERT_ARG, ~)); | |
547 | } | |
548 | }; | |
549 | ||
550 | template< | |
551 | class R | |
552 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) | |
553 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), | |
554 | class Concept | |
555 | > | |
556 | struct BOOST_PP_CAT(call_impl, N)< | |
557 | R | |
558 | BOOST_PP_ENUM_TRAILING_PARAMS(N, T) | |
559 | BOOST_PP_ENUM_TRAILING_PARAMS(N, U), | |
560 | Concept, | |
561 | true | |
562 | > | |
563 | { | |
564 | typedef ::boost::type_erasure::any<Concept, R> type; | |
565 | template<class F> | |
566 | static type apply(const ::boost::type_erasure::binding<Concept>* table | |
567 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, arg)) | |
568 | { | |
569 | return type(table->template find<F>()( | |
570 | BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_CONVERT_ARG, ~)), *table); | |
571 | } | |
572 | }; | |
573 | ||
574 | template< | |
575 | class R | |
576 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) | |
577 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), | |
578 | class Concept | |
579 | > | |
580 | struct call_impl<R(BOOST_PP_ENUM_PARAMS(N, T)), void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, u)), Concept, true> | |
581 | : BOOST_PP_CAT(call_impl, N)<R BOOST_PP_ENUM_TRAILING_PARAMS(N, T) BOOST_PP_ENUM_TRAILING_PARAMS(N, U), Concept> | |
582 | {}; | |
583 | ||
584 | #if N != 0 | |
585 | ||
586 | template< | |
587 | class R | |
588 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) | |
589 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) | |
590 | > | |
591 | struct call_impl<R(BOOST_PP_ENUM_PARAMS(N, T)), void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, u)), void, true> | |
592 | : BOOST_PP_CAT(call_impl, N)<R BOOST_PP_ENUM_TRAILING_PARAMS(N, T) BOOST_PP_ENUM_TRAILING_PARAMS(N, U)> | |
593 | {}; | |
594 | ||
595 | #endif | |
596 | ||
597 | } | |
598 | ||
599 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES | |
600 | #define RREF & | |
601 | #define BOOST_TYPE_ERASURE_FORWARD_ARGS(N, X, x) BOOST_PP_ENUM_TRAILING_PARAMS(N, x) | |
602 | #else | |
603 | #define RREF && | |
604 | #define BOOST_TYPE_ERASURE_FORWARD_ARGS_I(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)) | |
605 | #define BOOST_TYPE_ERASURE_FORWARD_ARGS(N, X, x) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_ARGS_I, (X, x)) | |
606 | #endif | |
607 | ||
608 | template< | |
609 | class Concept, | |
610 | class Op | |
611 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) | |
612 | > | |
613 | typename ::boost::type_erasure::detail::call_result< | |
614 | Op, | |
615 | void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)), | |
616 | Concept | |
617 | >::type | |
618 | unchecked_call( | |
619 | const ::boost::type_erasure::binding<Concept>& table, | |
620 | const Op& | |
621 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) | |
622 | { | |
623 | return ::boost::type_erasure::detail::call_impl< | |
624 | typename ::boost::type_erasure::detail::get_signature<Op>::type, | |
625 | void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)), | |
626 | Concept | |
627 | >::template apply< | |
628 | typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type | |
629 | >(&table BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); | |
630 | } | |
631 | ||
632 | template< | |
633 | class Concept, | |
634 | class Op | |
635 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) | |
636 | > | |
637 | typename ::boost::type_erasure::detail::call_result< | |
638 | Op, | |
639 | void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)), | |
640 | Concept | |
641 | >::type | |
642 | call( | |
643 | const ::boost::type_erasure::binding<Concept>& table, | |
644 | const Op& f | |
645 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) | |
646 | { | |
647 | ::boost::type_erasure::require_match(table, f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); | |
648 | return ::boost::type_erasure::unchecked_call(table, f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); | |
649 | } | |
650 | ||
651 | #if N != 0 | |
652 | ||
653 | template< | |
654 | class Op | |
655 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) | |
656 | > | |
657 | typename ::boost::type_erasure::detail::call_result< | |
658 | Op, | |
659 | void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)) | |
660 | >::type | |
661 | unchecked_call( | |
662 | const Op& | |
663 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) | |
664 | { | |
665 | return ::boost::type_erasure::detail::call_impl< | |
666 | typename ::boost::type_erasure::detail::get_signature<Op>::type, | |
667 | void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)) | |
668 | >::template apply< | |
669 | typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type | |
670 | >( | |
671 | ::boost::type_erasure::detail::BOOST_PP_CAT(extract_table, N)( | |
672 | (typename ::boost::type_erasure::detail::get_signature<Op>::type*)0, | |
673 | BOOST_PP_ENUM_PARAMS(N, arg)) | |
674 | BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg) | |
675 | ); | |
676 | } | |
677 | ||
678 | template< | |
679 | class Op | |
680 | BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) | |
681 | > | |
682 | typename ::boost::type_erasure::detail::call_result< | |
683 | Op, | |
684 | void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)) | |
685 | >::type | |
686 | call( | |
687 | const Op& f | |
688 | BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) | |
689 | { | |
690 | ::boost::type_erasure::require_match(f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); | |
691 | return ::boost::type_erasure::unchecked_call(f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); | |
692 | } | |
693 | ||
694 | #endif | |
695 | ||
696 | #undef RREF | |
697 | #undef BOOST_TYPE_ERASURE_FORWARD_ARGS | |
698 | #undef BOOST_TYPE_ERASURE_FORWARD_ARGS_I | |
699 | ||
700 | #undef BOOST_TYPE_ERASURE_GET_TABLE | |
701 | #undef BOOST_TYPE_ERASURE_CONVERT_ARG | |
702 | #undef N | |
703 | ||
704 | #endif |