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