705 lines
20 KiB
C++
705 lines
20 KiB
C++
// 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: call.hpp 83321 2013-03-05 21:27:18Z steven_watanabe $
|
|
|
|
#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
|