• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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