| // Boost.TypeErasure library |
| // |
| // Copyright 2011 Steven Watanabe |
| // |
| // Distributed under the Boost Software License Version 1.0. (See |
| // accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // $Id$ |
| |
| #if !defined(BOOST_PP_IS_ITERATING) |
| |
| #ifndef BOOST_TYPE_ERASURE_CALL_HPP_INCLUDED |
| #define BOOST_TYPE_ERASURE_CALL_HPP_INCLUDED |
| |
| #include <boost/assert.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/eval_if.hpp> |
| #include <boost/mpl/identity.hpp> |
| #include <boost/type_traits/remove_cv.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| #include <boost/preprocessor/cat.hpp> |
| #include <boost/preprocessor/inc.hpp> |
| #include <boost/preprocessor/iteration/iterate.hpp> |
| #include <boost/preprocessor/repetition/repeat.hpp> |
| #include <boost/preprocessor/repetition/enum.hpp> |
| #include <boost/preprocessor/repetition/enum_trailing.hpp> |
| #include <boost/preprocessor/repetition/enum_params.hpp> |
| #include <boost/preprocessor/repetition/enum_binary_params.hpp> |
| #include <boost/preprocessor/repetition/enum_trailing_params.hpp> |
| #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> |
| #include <boost/type_erasure/detail/access.hpp> |
| #include <boost/type_erasure/detail/adapt_to_vtable.hpp> |
| #include <boost/type_erasure/detail/extract_concept.hpp> |
| #include <boost/type_erasure/detail/get_signature.hpp> |
| #include <boost/type_erasure/detail/check_call.hpp> |
| #include <boost/type_erasure/is_placeholder.hpp> |
| #include <boost/type_erasure/concept_of.hpp> |
| #include <boost/type_erasure/config.hpp> |
| #include <boost/type_erasure/require_match.hpp> |
| |
| namespace boost { |
| namespace type_erasure { |
| |
| template<class Concept, class Placeholder> |
| class any; |
| |
| template<class Concept> |
| class binding; |
| |
| namespace detail { |
| |
| template<class T> |
| struct is_placeholder_arg : |
| ::boost::type_erasure::is_placeholder< |
| typename ::boost::remove_cv< |
| typename ::boost::remove_reference<T>::type |
| >::type |
| > |
| {}; |
| |
| template<class T, class Table> |
| int maybe_get_table(const T& arg, const Table*& table, boost::mpl::true_) |
| { |
| if(table == 0) { |
| table = &::boost::type_erasure::detail::access::table(arg); |
| } |
| return 0; |
| } |
| |
| template<class T, class Table> |
| int maybe_get_table(const T&, const Table*&, boost::mpl::false_) { return 0; } |
| |
| template<class T> |
| ::boost::type_erasure::detail::storage& convert_arg(any_base<T>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(any_base<any<Concept, const T&> >& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(const any_base<T>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage& |
| convert_arg(const any_base<any<Concept, T&> >& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(const any_base<any<Concept, const T&> >& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage& |
| convert_arg(param<Concept, T>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(param<Concept, const T&>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(const param<Concept, T>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| |
| template<class Concept, class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(any_base<any<Concept, const T&> >&& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage& |
| convert_arg(any_base<any<Concept, T&> >&& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage&& |
| convert_arg(any_base<any<Concept, T> >&& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(std::move(arg)); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage&& |
| convert_arg(any_base<any<Concept, T&&> >& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage&& |
| convert_arg(const any_base<any<Concept, T&&> >& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| const ::boost::type_erasure::detail::storage& |
| convert_arg(param<Concept, const T&>&& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage& |
| convert_arg(param<Concept, T&>&& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage&& |
| convert_arg(param<Concept, T>&& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(std::move(arg)); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage&& |
| convert_arg(param<Concept, T&&>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class Concept, class T> |
| ::boost::type_erasure::detail::storage&& |
| convert_arg(const param<Concept, T&&>& arg, boost::mpl::true_) |
| { |
| return ::boost::type_erasure::detail::access::data(arg); |
| } |
| |
| template<class T> |
| T&& convert_arg(T&& arg, boost::mpl::false_) { return std::forward<T>(arg); } |
| |
| #else |
| |
| template<class T> |
| T& convert_arg(T& arg, boost::mpl::false_) { return arg; } |
| |
| #endif |
| |
| } |
| |
| #ifdef BOOST_TYPE_ERASURE_DOXYGEN |
| |
| /** |
| * Dispatches a type erased function. |
| * |
| * @c Op must be a primitive concept which is present in |
| * @c Concept. Its signature determines how the arguments of |
| * \call are handled. If the argument is a @ref placeholder, |
| * \call expects an @ref any using that @ref placeholder. |
| * This @ref any is unwrapped by \call. The type that |
| * it stores must be the same type specified by @c binding. |
| * Any arguments that are not placeholders in the signature |
| * of @c Op are passed through unchanged. |
| * |
| * If @c binding is not specified, it will be deduced from |
| * the arguments. Naturally this requires at least one |
| * argument to be an @ref any. In this case, all @ref any |
| * arguments must have the same @ref binding. |
| * |
| * \return The result of the operation. If the result type |
| * of the signature of @c Op is a placeholder, the |
| * result will be converted to the appropriate @ref |
| * any type. |
| * |
| * \throws bad_function_call if @ref relaxed is |
| * in @c Concept and there is a type mismatch. |
| * |
| * Example: |
| * |
| * @code |
| * typedef mpl::vector< |
| * copy_constructible<_b>, |
| * addable<_a, int, _b> > concept; |
| * any<concept, _a> a = ...; |
| * any<concept, _b> b(call(addable<_a, int, _b>(), a, 10)); |
| * @endcode |
| * |
| * The signature of @ref addable is <code>_b(const _a&, const int&)</code> |
| */ |
| template<class Concept, class Op, class... U> |
| typename ::boost::type_erasure::detail::call_impl<Sig, U..., Concept>::type |
| call(const binding<Concept>& binding_arg, const Op&, U&&... args); |
| |
| /** |
| * \overload |
| */ |
| template<class Op, class... U> |
| typename ::boost::type_erasure::detail::call_impl<Sig, U...>::type |
| call(const Op&, U&&... args); |
| |
| #else |
| |
| namespace detail { |
| |
| template<class Sig, class Args, class Concept = void, |
| bool Check = ::boost::type_erasure::detail::check_call<Sig, Args>::type::value> |
| struct call_impl {}; |
| |
| template<class Op, class Args, class Concept = void> |
| struct call_result : |
| call_impl< |
| typename ::boost::type_erasure::detail::get_signature<Op>::type, |
| Args, |
| Concept> |
| {}; |
| |
| template<class C1, class Args, class Concept> |
| struct call_result< |
| ::boost::type_erasure::binding<C1>, |
| Args, |
| Concept |
| > |
| {}; |
| |
| } |
| |
| #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) |
| |
| namespace detail { |
| |
| template<class... T> |
| void ignore(const T&...) {} |
| |
| template<class R, class... T, class... U> |
| const ::boost::type_erasure::binding< |
| typename ::boost::type_erasure::detail::extract_concept<void(T...), U...>::type>* |
| extract_table(R(*)(T...), const U&... arg) |
| { |
| const ::boost::type_erasure::binding< |
| typename ::boost::type_erasure::detail::extract_concept< |
| void(T...), U...>::type>* result = 0; |
| |
| // the order that we run maybe_get_table in doesn't matter |
| ignore(::boost::type_erasure::detail::maybe_get_table( |
| arg, |
| result, |
| ::boost::type_erasure::detail::is_placeholder_arg<T>())...); |
| |
| BOOST_ASSERT(result != 0); |
| return result; |
| } |
| |
| template<class Sig, class Args, class Concept, bool ReturnsAny> |
| struct call_impl_dispatch; |
| |
| template<class R, class... T, class... U, class Concept> |
| struct call_impl_dispatch<R(T...), void(U...), Concept, false> |
| { |
| typedef R type; |
| template<class F> |
| static R apply(const ::boost::type_erasure::binding<Concept>* table, U... arg) |
| { |
| return table->template find<F>()( |
| ::boost::type_erasure::detail::convert_arg( |
| ::std::forward<U>(arg), |
| ::boost::type_erasure::detail::is_placeholder_arg<T>())...); |
| } |
| }; |
| |
| template<class R, class... T, class... U, class Concept> |
| struct call_impl_dispatch<R(T...), void(U...), Concept, true> |
| { |
| typedef ::boost::type_erasure::any<Concept, R> type; |
| template<class F> |
| static type apply(const ::boost::type_erasure::binding<Concept>* table, U... arg) |
| { |
| return type(table->template find<F>()( |
| ::boost::type_erasure::detail::convert_arg( |
| ::std::forward<U>(arg), |
| ::boost::type_erasure::detail::is_placeholder_arg<T>())...), *table); |
| } |
| }; |
| |
| template<class R, class... T, class... U, class Concept> |
| struct call_impl<R(T...), void(U...), Concept, true> : |
| ::boost::type_erasure::detail::call_impl_dispatch< |
| R(T...), |
| void(U...), |
| Concept, |
| ::boost::type_erasure::detail::is_placeholder_arg<R>::value |
| > |
| { |
| }; |
| |
| template<class R, class... T, class... U> |
| struct call_impl<R(T...), void(U...), void, true> : |
| ::boost::type_erasure::detail::call_impl_dispatch< |
| R(T...), |
| void(U...), |
| typename ::boost::type_erasure::detail::extract_concept< |
| void(T...), |
| typename ::boost::remove_reference<U>::type... |
| >::type, |
| ::boost::type_erasure::detail::is_placeholder_arg<R>::value |
| > |
| { |
| }; |
| |
| } |
| |
| template< |
| class Concept, |
| class Op, |
| class... U |
| > |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(U&&...), |
| Concept |
| >::type |
| unchecked_call( |
| const ::boost::type_erasure::binding<Concept>& table, |
| const Op&, |
| U&&... arg) |
| { |
| return ::boost::type_erasure::detail::call_impl< |
| typename ::boost::type_erasure::detail::get_signature<Op>::type, |
| void(U&&...), |
| Concept |
| >::template apply< |
| typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type |
| >(&table, std::forward<U>(arg)...); |
| } |
| |
| template<class Concept, class Op, class... U> |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(U&&...), |
| Concept |
| >::type |
| call( |
| const ::boost::type_erasure::binding<Concept>& table, |
| const Op& f, |
| U&&... arg) |
| { |
| ::boost::type_erasure::require_match(table, f, std::forward<U>(arg)...); |
| return ::boost::type_erasure::unchecked_call(table, f, std::forward<U>(arg)...); |
| } |
| |
| template<class Op, class... U> |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(U&&...) |
| >::type |
| unchecked_call( |
| const Op&, |
| U&&... arg) |
| { |
| return ::boost::type_erasure::detail::call_impl< |
| typename ::boost::type_erasure::detail::get_signature<Op>::type, |
| void(U&&...) |
| >::template apply< |
| typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type |
| >(::boost::type_erasure::detail::extract_table( |
| static_cast<typename ::boost::type_erasure::detail::get_signature<Op>::type*>(0), arg...), |
| std::forward<U>(arg)...); |
| } |
| |
| template<class Op, class... U> |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(U&&...) |
| >::type |
| call( |
| const Op& f, |
| U&&... arg) |
| { |
| ::boost::type_erasure::require_match(f, std::forward<U>(arg)...); |
| return ::boost::type_erasure::unchecked_call(f, std::forward<U>(arg)...); |
| } |
| |
| |
| #else |
| |
| #define BOOST_PP_FILENAME_1 <boost/type_erasure/call.hpp> |
| #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) |
| #include BOOST_PP_ITERATE() |
| |
| #endif |
| |
| #endif |
| |
| } |
| } |
| |
| #endif |
| |
| #else |
| |
| #define N BOOST_PP_ITERATION() |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| |
| #define BOOST_TYPE_ERASURE_CONVERT_ARG(z, n, data) \ |
| ::boost::type_erasure::detail::convert_arg( \ |
| std::forward<BOOST_PP_CAT(U, n)>(BOOST_PP_CAT(arg, n)), \ |
| ::boost::type_erasure::detail::is_placeholder_arg<BOOST_PP_CAT(T, n)>()) |
| |
| #else |
| |
| #define BOOST_TYPE_ERASURE_CONVERT_ARG(z, n, data) \ |
| ::boost::type_erasure::detail::convert_arg( \ |
| BOOST_PP_CAT(arg, n), \ |
| ::boost::type_erasure::detail::is_placeholder_arg<BOOST_PP_CAT(T, n)>()) |
| |
| #endif |
| |
| #define BOOST_TYPE_ERASURE_GET_TABLE(z, n, data) \ |
| ::boost::type_erasure::detail::maybe_get_table( \ |
| BOOST_PP_CAT(arg, n), \ |
| result, \ |
| ::boost::type_erasure::detail::is_placeholder_arg<BOOST_PP_CAT(T, n)>()); |
| |
| namespace detail { |
| |
| #if N != 0 |
| |
| template< |
| class R, |
| BOOST_PP_ENUM_PARAMS(N, class T), |
| BOOST_PP_ENUM_PARAMS(N, class U)> |
| const ::boost::type_erasure::binding< |
| typename ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)< |
| BOOST_PP_ENUM_PARAMS(N, T), |
| BOOST_PP_ENUM_PARAMS(N, U)>::type>* |
| BOOST_PP_CAT(extract_table, N)(R(*)(BOOST_PP_ENUM_PARAMS(N, T)), BOOST_PP_ENUM_BINARY_PARAMS(N, const U, &arg)) |
| { |
| const ::boost::type_erasure::binding< |
| typename ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)< |
| BOOST_PP_ENUM_PARAMS(N, T), |
| BOOST_PP_ENUM_PARAMS(N, U)>::type>* result = 0; |
| BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_GET_TABLE, ~) |
| BOOST_ASSERT(result != 0); |
| return result; |
| } |
| |
| #endif |
| |
| template< |
| class R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), |
| class Concept |
| #if N != 0 |
| = typename ::boost::type_erasure::detail::BOOST_PP_CAT(extract_concept, N)< |
| BOOST_PP_ENUM_PARAMS(N, T), |
| BOOST_PP_ENUM_PARAMS(N, U) |
| >::type |
| #endif |
| , |
| bool ReturnsAny = ::boost::type_erasure::detail::is_placeholder_arg<R>::value> |
| struct BOOST_PP_CAT(call_impl, N); |
| |
| template< |
| class R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), |
| class Concept |
| > |
| struct BOOST_PP_CAT(call_impl, N)< |
| R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, U), |
| Concept, |
| false |
| > |
| { |
| typedef R type; |
| template<class F> |
| static R apply(const ::boost::type_erasure::binding<Concept>* table |
| BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, arg)) |
| { |
| return table->template find<F>()( |
| BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_CONVERT_ARG, ~)); |
| } |
| }; |
| |
| template< |
| class R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), |
| class Concept |
| > |
| struct BOOST_PP_CAT(call_impl, N)< |
| R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, U), |
| Concept, |
| true |
| > |
| { |
| typedef ::boost::type_erasure::any<Concept, R> type; |
| template<class F> |
| static type apply(const ::boost::type_erasure::binding<Concept>* table |
| BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, arg)) |
| { |
| return type(table->template find<F>()( |
| BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_CONVERT_ARG, ~)), *table); |
| } |
| }; |
| |
| template< |
| class R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U), |
| class Concept |
| > |
| struct call_impl<R(BOOST_PP_ENUM_PARAMS(N, T)), void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, u)), Concept, true> |
| : BOOST_PP_CAT(call_impl, N)<R BOOST_PP_ENUM_TRAILING_PARAMS(N, T) BOOST_PP_ENUM_TRAILING_PARAMS(N, U), Concept> |
| {}; |
| |
| #if N != 0 |
| |
| template< |
| class R |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class T) |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) |
| > |
| struct call_impl<R(BOOST_PP_ENUM_PARAMS(N, T)), void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, u)), void, true> |
| : BOOST_PP_CAT(call_impl, N)<R BOOST_PP_ENUM_TRAILING_PARAMS(N, T) BOOST_PP_ENUM_TRAILING_PARAMS(N, U)> |
| {}; |
| |
| #endif |
| |
| } |
| |
| #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
| #define RREF & |
| #define BOOST_TYPE_ERASURE_FORWARD_ARGS(N, X, x) BOOST_PP_ENUM_TRAILING_PARAMS(N, x) |
| #else |
| #define RREF && |
| #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)) |
| #define BOOST_TYPE_ERASURE_FORWARD_ARGS(N, X, x) BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_FORWARD_ARGS_I, (X, x)) |
| #endif |
| |
| template< |
| class Concept, |
| class Op |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) |
| > |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)), |
| Concept |
| >::type |
| unchecked_call( |
| const ::boost::type_erasure::binding<Concept>& table, |
| const Op& |
| BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) |
| { |
| return ::boost::type_erasure::detail::call_impl< |
| typename ::boost::type_erasure::detail::get_signature<Op>::type, |
| void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)), |
| Concept |
| >::template apply< |
| typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type |
| >(&table BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); |
| } |
| |
| template< |
| class Concept, |
| class Op |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) |
| > |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)), |
| Concept |
| >::type |
| call( |
| const ::boost::type_erasure::binding<Concept>& table, |
| const Op& f |
| BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) |
| { |
| ::boost::type_erasure::require_match(table, f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); |
| return ::boost::type_erasure::unchecked_call(table, f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); |
| } |
| |
| #if N != 0 |
| |
| template< |
| class Op |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) |
| > |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)) |
| >::type |
| unchecked_call( |
| const Op& |
| BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) |
| { |
| return ::boost::type_erasure::detail::call_impl< |
| typename ::boost::type_erasure::detail::get_signature<Op>::type, |
| void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)) |
| >::template apply< |
| typename ::boost::type_erasure::detail::adapt_to_vtable<Op>::type |
| >( |
| ::boost::type_erasure::detail::BOOST_PP_CAT(extract_table, N)( |
| (typename ::boost::type_erasure::detail::get_signature<Op>::type*)0, |
| BOOST_PP_ENUM_PARAMS(N, arg)) |
| BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg) |
| ); |
| } |
| |
| template< |
| class Op |
| BOOST_PP_ENUM_TRAILING_PARAMS(N, class U) |
| > |
| typename ::boost::type_erasure::detail::call_result< |
| Op, |
| void(BOOST_PP_ENUM_BINARY_PARAMS(N, U, RREF u)) |
| >::type |
| call( |
| const Op& f |
| BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, U, RREF arg)) |
| { |
| ::boost::type_erasure::require_match(f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); |
| return ::boost::type_erasure::unchecked_call(f BOOST_TYPE_ERASURE_FORWARD_ARGS(N, U, arg)); |
| } |
| |
| #endif |
| |
| #undef RREF |
| #undef BOOST_TYPE_ERASURE_FORWARD_ARGS |
| #undef BOOST_TYPE_ERASURE_FORWARD_ARGS_I |
| |
| #undef BOOST_TYPE_ERASURE_GET_TABLE |
| #undef BOOST_TYPE_ERASURE_CONVERT_ARG |
| #undef N |
| |
| #endif |