summaryrefslogtreecommitdiff
path: root/boost/type_erasure/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/type_erasure/detail')
-rw-r--r--boost/type_erasure/detail/access.hpp105
-rw-r--r--boost/type_erasure/detail/adapt_to_vtable.hpp19
-rw-r--r--boost/type_erasure/detail/any_base.hpp4
-rw-r--r--boost/type_erasure/detail/check_call.hpp72
-rw-r--r--boost/type_erasure/detail/check_map.hpp50
-rw-r--r--boost/type_erasure/detail/dynamic_vtable.hpp22
-rw-r--r--boost/type_erasure/detail/extract_concept.hpp32
-rw-r--r--boost/type_erasure/detail/get_placeholders.hpp102
-rw-r--r--boost/type_erasure/detail/instantiate.hpp60
-rw-r--r--boost/type_erasure/detail/member11.hpp214
-rw-r--r--boost/type_erasure/detail/meta.hpp89
-rw-r--r--boost/type_erasure/detail/normalize.hpp446
-rw-r--r--boost/type_erasure/detail/normalize_deduced.hpp5
-rw-r--r--boost/type_erasure/detail/null.hpp14
-rw-r--r--boost/type_erasure/detail/rebind_placeholders.hpp158
-rw-r--r--boost/type_erasure/detail/storage.hpp7
-rw-r--r--boost/type_erasure/detail/vtable.hpp11
17 files changed, 1341 insertions, 69 deletions
diff --git a/boost/type_erasure/detail/access.hpp b/boost/type_erasure/detail/access.hpp
index 4116bf1ceb..84c61931bb 100644
--- a/boost/type_erasure/detail/access.hpp
+++ b/boost/type_erasure/detail/access.hpp
@@ -14,6 +14,18 @@
#include <boost/type_erasure/detail/storage.hpp>
#include <boost/type_erasure/detail/any_base.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
+ !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, == 1800) && \
+ !BOOST_WORKAROUND(BOOST_GCC, < 40800) && /* Inherited constructors */ \
+ !(defined(__clang_major__) && __clang_major__ == 3 && __clang__minor__ <= 2) /* Inherited constructors */
+#define BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/utility/enable_if.hpp>
+#endif
+
namespace boost {
namespace type_erasure {
@@ -23,6 +35,9 @@ class any;
template<class Concept, class T>
class param;
+template<class Concept>
+class binding;
+
namespace detail {
struct access
@@ -34,11 +49,51 @@ struct access
return static_cast<const Derived&>(arg).table;
}
template<class Concept, class T>
- static const typename any<Concept, T>::table_type&
+ static const ::boost::type_erasure::binding<Concept>&
table(const ::boost::type_erasure::param<Concept, T>& arg)
{
+ return table(arg._impl);
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::binding<Concept>&
+ table(const ::boost::type_erasure::param<Concept, T&>& arg)
+ {
+ return arg._impl.table;
+ }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<class Concept, class T>
+ static const ::boost::type_erasure::binding<Concept>&
+ table(const ::boost::type_erasure::param<Concept, T&&>& arg)
+ {
return arg._impl.table;
}
+#endif
+#ifdef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS
+ template<class Concept, class T, class = typename ::boost::enable_if_c<!::boost::is_reference<T>::value>::type>
+ static const typename any<Concept, T>::table_type&
+ table(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >& arg)
+ {
+ return static_cast<const ::boost::type_erasure::any<Concept, T>&>(arg)._boost_type_erasure_table;
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >& arg)
+ {
+ return static_cast< ::boost::type_erasure::any<Concept, T>&>(arg)._boost_type_erasure_data;
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >& arg)
+ {
+ return static_cast<const ::boost::type_erasure::any<Concept, T>&>(arg)._boost_type_erasure_data;
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >&& arg)
+ {
+ return std::move(static_cast< ::boost::type_erasure::any<Concept, T>&&>(arg)._boost_type_erasure_data);
+ }
+#endif
template<class Derived>
static ::boost::type_erasure::detail::storage&
data(::boost::type_erasure::any_base<Derived>& arg)
@@ -59,6 +114,12 @@ struct access
}
template<class Concept, class T>
static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >& arg)
+ {
+ return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< ::boost::type_erasure::any<Concept, T&>&>(arg).data);
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >& arg)
{
return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any<Concept, T&>&>(arg).data);
@@ -73,6 +134,12 @@ struct access
static ::boost::type_erasure::detail::storage&
data(::boost::type_erasure::param<Concept, T>& arg)
{
+ return data(arg._impl);
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::param<Concept, T&>& arg)
+ {
return arg._impl.data;
}
template<class Concept, class T>
@@ -85,6 +152,12 @@ struct access
static const ::boost::type_erasure::detail::storage&
data(const ::boost::type_erasure::param<Concept, T>& arg)
{
+ return data(arg._impl);
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(const ::boost::type_erasure::param<Concept, T&>& arg)
+ {
return arg._impl.data;
}
@@ -104,18 +177,48 @@ struct access
}
template<class Concept, class T>
static ::boost::type_erasure::detail::storage&&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&&> >&& arg)
+ {
+ return std::move(static_cast< ::boost::type_erasure::any<Concept, T&&>&>(arg).data);
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&&
data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&&> >& arg)
{
return std::move(const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any<Concept, T&&>&>(arg).data));
}
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >&& arg)
+ {
+ return std::move(static_cast< ::boost::type_erasure::any<Concept, T&>&>(arg).data);
+ }
template<class Concept, class T>
static ::boost::type_erasure::detail::storage&&
data(::boost::type_erasure::param<Concept, T>&& arg)
{
+ return std::move(data(arg._impl));
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&&
+ data(::boost::type_erasure::param<Concept, T&&>&& arg)
+ {
return std::move(arg._impl.data);
}
template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::param<Concept, T&>&& arg)
+ {
+ return arg._impl.data;
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::param<Concept, const T&>&& arg)
+ {
+ return arg._impl.data;
+ }
+ template<class Concept, class T>
static ::boost::type_erasure::detail::storage&&
data(::boost::type_erasure::param<Concept, T&&>& arg)
{
diff --git a/boost/type_erasure/detail/adapt_to_vtable.hpp b/boost/type_erasure/detail/adapt_to_vtable.hpp
index e58ddc8599..f842dc3985 100644
--- a/boost/type_erasure/detail/adapt_to_vtable.hpp
+++ b/boost/type_erasure/detail/adapt_to_vtable.hpp
@@ -39,24 +39,9 @@ namespace detail {
template<class T, class Out>
struct get_placeholders;
-template<class T, class Bindings>
-struct rebind_placeholders;
-
-template<class T, class Bindings>
-struct rebind_placeholders_in_argument;
-
template<class PrimitiveConcept, class Sig>
struct vtable_adapter;
-template<class PrimitiveConcept, class Sig, class Bindings>
-struct rebind_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Bindings>
-{
- typedef vtable_adapter<
- typename rebind_placeholders<PrimitiveConcept, Bindings>::type,
- typename rebind_placeholders_in_argument<Sig, Bindings>::type
- > type;
-};
-
template<class PrimitiveConcept, class Sig, class Out>
struct get_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Out>
{
@@ -308,11 +293,13 @@ struct vtable_adapter<PrimitiveConcept, R(BOOST_PP_ENUM_PARAMS(N, T))>
typedef R (*type)(BOOST_PP_ENUM_PARAMS(N, T));
static R value(BOOST_PP_ENUM_BINARY_PARAMS(N, T, arg))
{
+#if N > 0
typedef typename ::boost::function_traits<
typename ::boost::type_erasure::detail::get_signature<
PrimitiveConcept
>::type
> traits;
+#endif
return PrimitiveConcept::apply(
BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_EXTRACT, ~));
}
@@ -325,11 +312,13 @@ struct vtable_adapter<PrimitiveConcept, ::boost::type_erasure::detail::storage(B
typedef ::boost::type_erasure::detail::storage (*type)(BOOST_PP_ENUM_PARAMS(N, T));
static ::boost::type_erasure::detail::storage value(BOOST_PP_ENUM_BINARY_PARAMS(N, T, arg))
{
+#if N > 0
typedef typename ::boost::function_traits<
typename ::boost::type_erasure::detail::get_signature<
PrimitiveConcept
>::type
> traits;
+#endif
return ::boost::type_erasure::detail::storage(
PrimitiveConcept::apply(
BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_EXTRACT, ~)));
diff --git a/boost/type_erasure/detail/any_base.hpp b/boost/type_erasure/detail/any_base.hpp
index 0fa316c9ff..b7c4f8c050 100644
--- a/boost/type_erasure/detail/any_base.hpp
+++ b/boost/type_erasure/detail/any_base.hpp
@@ -19,7 +19,9 @@ struct any_base
{
typedef void _boost_type_erasure_is_any;
typedef Derived _boost_type_erasure_derived_type;
- void* _boost_type_erasure_deduce_constructor(...) { return 0; }
+ // volatile makes this a worse match than the default constructor
+ // for msvc-14.1, which can get confused otherwise.
+ void* _boost_type_erasure_deduce_constructor(...) const volatile { return 0; }
void* _boost_type_erasure_deduce_assign(...) { return 0; }
};
diff --git a/boost/type_erasure/detail/check_call.hpp b/boost/type_erasure/detail/check_call.hpp
index adf36dbeaa..daa9931146 100644
--- a/boost/type_erasure/detail/check_call.hpp
+++ b/boost/type_erasure/detail/check_call.hpp
@@ -113,10 +113,53 @@ struct check_placeholder_arg :
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
((defined(__GNUC__) && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))) || \
- defined(__MINGW32__) || defined(__MINGW64__))
+ defined(__MINGW32__) || defined(__MINGW64__) || \
+ BOOST_WORKAROUND(BOOST_MSVC, <= 1700))
#define BOOST_TYPE_ERASURE_BROKEN_RVALUE_IS_CONVERTIBLE
#endif
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class P, class Arg>
+using check_placeholder_arg_t =
+ typename ::boost::type_erasure::detail::check_placeholder_arg_impl<
+ P,
+ typename ::boost::type_erasure::detail::qualified_placeholder<Arg>::type
+ >::type;
+
+template<class T, class Arg>
+using check_nonplaceholder_arg_t = typename ::boost::is_convertible<Arg, T>::type;
+
+template<class FormalArg, class ActualArg>
+using check_arg_t =
+ ::boost::type_erasure::detail::eval_if<
+ ::boost::type_erasure::is_placeholder<
+ ::boost::remove_cv_t<
+ ::boost::remove_reference_t<FormalArg>
+ >
+ >::value,
+ ::boost::type_erasure::detail::check_placeholder_arg_t,
+ ::boost::type_erasure::detail::check_nonplaceholder_arg_t,
+ FormalArg,
+ ActualArg
+ >;
+
+// MSVC 14.1 ICE's if we use check_arg_t directly.
+template<class FormalArg, class ActualArg>
+struct check_arg
+{
+ typedef ::boost::type_erasure::detail::check_arg_t<FormalArg, ActualArg> type;
+};
+
+template<class R, class... T, class... U>
+struct check_call<R(T...), void(U...)> {
+ typedef ::boost::mp11::mp_all<
+ typename ::boost::type_erasure::detail::check_arg<T, U>::type...
+ > type;
+};
+
+#else
+
template<class FormalArg, class ActualArg>
struct check_arg
{
@@ -135,10 +178,37 @@ struct check_arg
>::type type;
};
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/check_call.hpp>
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY)
#include BOOST_PP_ITERATE()
+#else
+
+template<class... B>
+struct and_;
+
+template<class T1, class... T>
+struct and_<T1, T...> : boost::mpl::eval_if_c<T1::type::value, and_<T...>, boost::mpl::false_>::type {};
+
+template<class T1>
+struct and_<T1> : T1::type {};
+
+template<>
+struct and_<> : boost::mpl::true_ {};
+
+template<class R, class... T, class... U>
+struct check_call<R(T...), void(U...)> {
+ typedef typename ::boost::type_erasure::detail::and_<
+ ::boost::type_erasure::detail::check_arg<T, U>...
+ >::type type;
+};
+
+#endif
+
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/check_map.hpp b/boost/type_erasure/detail/check_map.hpp
index a51c95deb0..d39b61fba2 100644
--- a/boost/type_erasure/detail/check_map.hpp
+++ b/boost/type_erasure/detail/check_map.hpp
@@ -37,8 +37,18 @@ struct is_deduced< ::boost::type_erasure::deduced<T> > : boost::mpl::true_ {};
// returns true if Map has a key for every non-deduced placeholder in Concept
template<class Concept, class Map>
struct check_map {
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
typedef typename normalize_concept<Concept>::basic basic_components;
-
+
+ typedef typename ::boost::mpl::fold<
+ basic_components,
+ ::boost::mpl::set0<>,
+ ::boost::type_erasure::detail::get_placeholders<
+ ::boost::mpl::_2,
+ ::boost::mpl::_1
+ >
+ >::type placeholders;
+
// Every non-deduced placeholder referenced in this
// map is indirectly deduced.
typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
@@ -51,15 +61,6 @@ struct check_map {
::boost::mpl::second< ::boost::mpl::_2>
>
>::type indirect_deduced_placeholders;
-
- typedef typename ::boost::mpl::fold<
- basic_components,
- ::boost::mpl::set0<>,
- ::boost::type_erasure::detail::get_placeholders<
- ::boost::mpl::_2,
- ::boost::mpl::_1
- >
- >::type placeholders;
typedef typename ::boost::is_same<
typename ::boost::mpl::find_if<
placeholders,
@@ -73,6 +74,35 @@ struct check_map {
>::type,
typename ::boost::mpl::end<placeholders>::type
>::type type;
+
+#else
+ typedef ::boost::type_erasure::detail::get_all_placeholders<
+ ::boost::type_erasure::detail::normalize_concept_t<Concept>
+ > placeholders;
+
+ // Every non-deduced placeholder referenced in this
+ // map is indirectly deduced.
+ typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
+ Concept>::type placeholder_subs;
+ typedef ::boost::mp11::mp_unique<
+ ::boost::mp11::mp_append<
+ ::boost::mp11::mp_transform<
+ ::boost::mp11::mp_first,
+ ::boost::type_erasure::detail::make_mp_list<Map>
+ >,
+ ::boost::mp11::mp_transform<
+ ::boost::mp11::mp_second,
+ ::boost::type_erasure::detail::make_mp_list<placeholder_subs>
+ >
+ >
+ > okay_placeholders;
+ template<class P>
+ using check_placeholder = ::boost::mpl::or_<
+ ::boost::type_erasure::detail::is_deduced<P>,
+ ::boost::mp11::mp_set_contains<okay_placeholders, P>
+ >;
+ typedef ::boost::mp11::mp_all_of<placeholders, check_placeholder> type;
+#endif
};
template<class Concept, class Map>
diff --git a/boost/type_erasure/detail/dynamic_vtable.hpp b/boost/type_erasure/detail/dynamic_vtable.hpp
index 9e014ed61b..959f2f3a32 100644
--- a/boost/type_erasure/detail/dynamic_vtable.hpp
+++ b/boost/type_erasure/detail/dynamic_vtable.hpp
@@ -32,9 +32,15 @@ namespace detail {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
template<class P>
-struct dynamic_binding_impl
-{
+struct dynamic_binding_impl {
const std::type_info * type;
+ dynamic_binding_impl() = default;
+ constexpr dynamic_binding_impl(const std::type_info * t) : type(t) {}
+};
+
+template<class T>
+struct dynamic_binding_element {
+ typedef const std::type_info * type;
};
template<class Table>
@@ -50,12 +56,15 @@ struct append_to_key {
template<class... P>
struct dynamic_vtable : dynamic_binding_impl<P>... {
dynamic_vtable() = default;
- template<class... T>
- constexpr dynamic_vtable(T* ...t) : dynamic_binding_impl<P>{t}... {}
+ constexpr dynamic_vtable(typename dynamic_binding_element<P>::type ...t) : dynamic_binding_impl<P>(t)... {}
template<class F>
typename F::type lookup(F*) const {
key_type key;
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mpl::set0<> >::type placeholders;
+#else
+ typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mp11::mp_list<> >::type placeholders;
+#endif
typedef typename ::boost::mpl::fold<
placeholders,
::boost::mpl::map0<>,
@@ -71,8 +80,13 @@ struct dynamic_vtable : dynamic_binding_impl<P>... {
}
template<class Bindings, class Src>
void convert_from(const Src& src) {
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
*this = dynamic_vtable(
(&src.lookup((::boost::type_erasure::typeid_<typename ::boost::mpl::at<Bindings, P>::type>*)0)())...);
+#else
+ *this = dynamic_vtable(
+ (&src.lookup((::boost::type_erasure::typeid_< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Bindings, P> > >*)0)())...);
+#endif
}
};
diff --git a/boost/type_erasure/detail/extract_concept.hpp b/boost/type_erasure/detail/extract_concept.hpp
index f519045d6c..0b1ce5d2fa 100644
--- a/boost/type_erasure/detail/extract_concept.hpp
+++ b/boost/type_erasure/detail/extract_concept.hpp
@@ -42,6 +42,33 @@ struct combine_concepts<void, T> { typedef T type; };
template<>
struct combine_concepts<void, void> { typedef void type; };
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class T, class U>
+using combine_concepts_t = typename ::boost::type_erasure::detail::combine_concepts<T, U>::type;
+
+template<class T, class U>
+using extract_concept_or_void =
+ ::boost::mp11::mp_eval_if_c<
+ !::boost::type_erasure::is_placeholder<
+ ::boost::remove_cv_t<
+ ::boost::remove_reference_t<T>
+ >
+ >::value,
+ void,
+ ::boost::type_erasure::concept_of_t, U
+ >;
+
+template<class L1, class L2>
+using extract_concept_t =
+ ::boost::mp11::mp_fold<
+ ::boost::mp11::mp_transform< ::boost::type_erasure::detail::extract_concept_or_void, L1, L2>,
+ void,
+ ::boost::type_erasure::detail::combine_concepts_t
+ >;
+
+#else
+
template<class T, class U>
struct maybe_extract_concept
{
@@ -56,7 +83,7 @@ struct maybe_extract_concept
>::type type;
};
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class Args, class... U>
struct extract_concept;
@@ -82,7 +109,6 @@ struct extract_concept<void()>
};
#else
-//#endif
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/extract_concept.hpp>
#define BOOST_PP_ITERATION_LIMITS (1, BOOST_TYPE_ERASURE_MAX_ARITY)
@@ -90,6 +116,8 @@ struct extract_concept<void()>
#endif
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/get_placeholders.hpp b/boost/type_erasure/detail/get_placeholders.hpp
index cdee16fc03..a17d2d445c 100644
--- a/boost/type_erasure/detail/get_placeholders.hpp
+++ b/boost/type_erasure/detail/get_placeholders.hpp
@@ -21,6 +21,7 @@
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
#include <boost/type_erasure/config.hpp>
#include <boost/type_erasure/is_placeholder.hpp>
@@ -28,6 +29,87 @@ namespace boost {
namespace type_erasure {
namespace detail {
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class T>
+struct get_placeholders_in_argument_impl
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::eval_if<
+ ::boost::type_erasure::is_placeholder<T>::value,
+ ::boost::mp11::mp_set_push_back,
+ ::boost::type_erasure::detail::first,
+ Out, T
+ >;
+};
+
+template<class T>
+struct get_placeholders_in_argument_impl<T&>
+{
+ template<class Out>
+ using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl<T>::template apply<Out>;
+};
+
+template<class T>
+struct get_placeholders_in_argument_impl<T&&>
+{
+ template<class Out>
+ using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl<T>::template apply<Out>;
+};
+
+template<class T>
+struct get_placeholders_in_argument_impl<const T>
+{
+ template<class Out>
+ using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl<T>::template apply<Out>;
+};
+
+template<class Out, class T>
+using get_placeholders_f = typename get_placeholders_in_argument_impl<T>::template apply<Out>;
+
+template<class Out, class... T>
+using get_placeholders_impl =
+ ::boost::mp11::mp_fold<
+ ::boost::mp11::mp_list<T...>,
+ Out,
+ ::boost::type_erasure::detail::get_placeholders_f
+ >;
+
+template<class R, class... T>
+struct get_placeholders_in_argument_impl<R(T...)>
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::get_placeholders_impl<Out, R, T...>;
+};
+
+template<class R, class C, class... T>
+struct get_placeholders_in_argument_impl<R (C::*)(T...)>
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::get_placeholders_impl<Out, R, C, T...>;
+};
+
+template<class R, class C, class... T>
+struct get_placeholders_in_argument_impl<R (C::*)(T...) const>
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::get_placeholders_impl<Out, R, C, T...>;
+};
+
+template<class T, class Out>
+struct get_placeholders;
+
+template<template<class...> class F, class... T, class Out>
+struct get_placeholders<F<T...>, Out>
+{
+ using type = ::boost::type_erasure::detail::get_placeholders_impl<Out, T...>;
+};
+
+template<class T, class Out>
+using get_placeholders_t = typename ::boost::type_erasure::detail::get_placeholders<T, Out>::type;
+
+#else
+
template<class T, class Out>
struct get_placeholders_in_argument
{
@@ -88,11 +170,19 @@ struct get_placeholders<T<U...>, Out>
template<class R, class... T, class Out>
struct get_placeholders_in_argument<R(T...), Out>
{
- typedef typename ::boost::type_erasure::detail::get_placeholders_in_argument<
- R,
- Out
- >::type type0;
- typedef typename get_placeholders_impl<type0, T...>::type type;
+ typedef typename get_placeholders_impl<Out, R, T...>::type type;
+};
+
+template<class R, class C, class... T, class Out>
+struct get_placeholders_in_argument<R (C::*)(T...), Out>
+{
+ typedef typename get_placeholders_impl<Out, R, C, T...>::type type;
+};
+
+template<class R, class C, class... T, class Out>
+struct get_placeholders_in_argument<R (C::*)(T...) const, Out>
+{
+ typedef typename get_placeholders_impl<Out, R, C, T...>::type type;
};
#else
@@ -103,6 +193,8 @@ struct get_placeholders_in_argument<R(T...), Out>
#endif
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/instantiate.hpp b/boost/type_erasure/detail/instantiate.hpp
index 74f3d27f83..742aa02a9b 100644
--- a/boost/type_erasure/detail/instantiate.hpp
+++ b/boost/type_erasure/detail/instantiate.hpp
@@ -28,6 +28,62 @@ namespace boost {
namespace type_erasure {
namespace detail {
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class L>
+struct make_instantiate_concept_impl;
+
+template<class T, T t>
+struct instantiate_concept;
+
+template<class T>
+using instantiate_concept_impl = instantiate_concept<decltype(&T::apply), &T::apply>;
+
+template<class... T>
+struct make_instantiate_concept_impl< ::boost::mp11::mp_list<T...> >
+{
+ template<template<class> class F>
+ using apply = void(F<T>...);
+};
+
+template<class Map>
+struct instantiate_concept_rebind_f
+{
+ template<class T>
+ using apply =
+ typename ::boost::type_erasure::detail::rebind_placeholders<
+ T,
+ Map
+ >::type;
+};
+
+template<class Concept, class Map>
+using make_instantiate_concept =
+ ::boost::type_erasure::detail::make_instantiate_concept_impl<
+ ::boost::mp11::mp_transform<
+ ::boost::type_erasure::detail::instantiate_concept_rebind_f<
+ typename ::boost::type_erasure::detail::add_deductions<
+ ::boost::type_erasure::detail::make_mp_list<Map>,
+ typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
+ Concept
+ >::type
+ >::type
+ >::template apply,
+ ::boost::type_erasure::detail::normalize_concept_t<Concept>
+ >
+ >;
+
+#define BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map) \
+ ((void)(typename ::boost::type_erasure::detail::make_instantiate_concept<Concept, Map> \
+ ::template apply< ::boost::type_erasure::detail::instantiate_concept_impl>*)0)
+
+#define BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, P0, T0) \
+ ((void)(typename ::boost::type_erasure::detail::make_instantiate_concept< \
+ Concept, ::boost::mpl::map1< ::boost::mpl::pair<P0, T0> > > \
+ ::template apply< ::boost::type_erasure::detail::instantiate_concept_impl>*)0)
+
+#else
+
template<int N>
struct make_instantiate_concept_impl;
@@ -56,6 +112,8 @@ struct make_instantiate_concept {
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_FUNCTIONS)
#include BOOST_PP_ITERATE()
+#endif
+
}
}
}
@@ -72,6 +130,7 @@ struct make_instantiate_concept {
struct BOOST_PP_CAT(instantiate_concept, N) {
template<class Concept, class Map>
static void apply(Concept *, Map *) {
+#if N > 0
typedef typename ::boost::type_erasure::detail::normalize_concept<
Concept>::type normalized;
typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
@@ -88,6 +147,7 @@ struct BOOST_PP_CAT(instantiate_concept, N) {
>::type
>
>::type concept_sequence;
+#endif
BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_INSTANTIATE_IMPL, concept_sequence)
}
};
diff --git a/boost/type_erasure/detail/member11.hpp b/boost/type_erasure/detail/member11.hpp
new file mode 100644
index 0000000000..7bc8eee6a9
--- /dev/null
+++ b/boost/type_erasure/detail/member11.hpp
@@ -0,0 +1,214 @@
+// Boost.TypeErasure library
+//
+// Copyright 2018 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$
+
+#ifndef BOOST_TYPE_ERASURE_DETAIL_MEMBER11_HPP_INCLUDED
+#define BOOST_TYPE_ERASURE_DETAIL_MEMBER11_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_DECLTYPE) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/punctuation/is_begin_parens.hpp>
+#include <boost/vmd/is_empty.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_erasure/detail/const.hpp>
+#include <boost/type_erasure/detail/macro.hpp>
+#include <boost/type_erasure/rebind_any.hpp>
+#include <boost/type_erasure/param.hpp>
+#include <boost/type_erasure/is_placeholder.hpp>
+#include <boost/type_erasure/call.hpp>
+
+namespace boost {
+namespace type_erasure {
+namespace detail {
+
+template<class P, template<class ...> class interface, class Sig, class Concept, class Base, class ID>
+using choose_member_interface = typename ::boost::mpl::if_c< ::boost::is_reference<P>::value,
+ typename ::boost::mpl::if_c< ::boost::type_erasure::detail::is_non_const_ref<P>::value,
+ interface<Sig, Concept, Base, const ID>,
+ Base
+ >::type,
+ interface<Sig, Concept, Base, ID>
+>::type;
+
+
+struct dummy {};
+
+template<class Sig>
+struct choose_member_impl;
+
+template<class R, class C, class... T>
+struct choose_member_impl<R (C::*)(T...) const>
+{
+ template<class P, template<class> class M, template<class,class> class S>
+ using apply = ::boost::mpl::vector1<S<R(T...), const P> >;
+};
+
+template<class R, class C, class... T>
+struct choose_member_impl<R (C::*)(T...)>
+{
+ template<class P, template<class> class M, template<class,class> class S>
+ using apply = M<R(P&, T...)>;
+};
+
+template<class Sig, class P, template<class> class M, template<class, class> class Self>
+using choose_member_impl_t =
+ typename ::boost::type_erasure::detail::choose_member_impl<
+ Sig (::boost::type_erasure::detail::dummy::*)
+ >::template apply<P, M, Self>;
+
+template<class Sig, class T, class ID>
+struct member_interface_chooser
+{
+ template<class Base, template<class, class> class C, template<class...> class M>
+ using apply = Base;
+};
+
+template<class R, class T, class... A>
+struct member_interface_chooser<R(A...), T, T>
+{
+ template<class Base, template<class, class> class C, template<class...> class M>
+ using apply = ::boost::type_erasure::detail::choose_member_interface<
+ ::boost::type_erasure::placeholder_of_t<Base>,
+ M,
+ R(A...), C<R(A...), T>, Base, T>;
+};
+
+template<class R, class T, class... A>
+struct member_interface_chooser<R(A...), const T, T>
+{
+ template<class Base, template<class, class> class C, template<class...> class M>
+ using apply = M<R(A...), C<R(A...), const T>, Base, const T>;
+};
+
+template<class Sig, class T, template<class, class> class C, template<class...> class M>
+struct member_choose_interface
+{
+ template<class Concept, class Base, class ID>
+ using apply = typename ::boost::type_erasure::detail::member_interface_chooser<Sig, T, ID>::template apply<Base, C, M>;
+};
+
+}
+}
+}
+
+#define BOOST_TYPE_ERASURE_MEMBER_I(concept_name, function_name) \
+template<class Sig, class T = ::boost::type_erasure::_self> \
+struct concept_name; \
+ \
+namespace boost_type_erasure_impl { \
+ \
+template<class Sig, class T> \
+using concept_name ## self = concept_name<Sig, T>; \
+ \
+template<class Sig, class Concept, class Base, class ID, class Enable = void>\
+struct concept_name ## _member_interface; \
+ \
+template<class R, class... A, class Concept, class Base, class ID, class V> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, ID, V> : Base\
+{ \
+ typedef void _boost_type_erasure_has_member ## function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class R, class... A, class Concept, class Base, class ID> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, ID, \
+ typename Base::_boost_type_erasure_has_member ## function_name> : Base \
+{ \
+ using Base::function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class R, class... A, class Concept, class Base, class ID, class V> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, V> : Base\
+{ \
+ typedef void _boost_type_erasure_has_member ## function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class R, class... A, class Concept, class Base, class ID> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, \
+ typename Base::_boost_type_erasure_has_member ## function_name> : Base \
+{ \
+ using Base::function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class Sig> \
+struct concept_name ## member; \
+ \
+template<class R, class T0, class... T> \
+struct concept_name ## member<R(T0, T...)> { \
+ static R apply(T0 t0, T... t) \
+ { return t0.function_name(std::forward<T>(t)...); } \
+}; \
+ \
+template<class T0, class... T> \
+struct concept_name ## member<void(T0, T...)> { \
+ static void apply(T0 t0, T... t) \
+ { t0.function_name(std::forward<T>(t)...); } \
+}; \
+ \
+} \
+ \
+template<class Sig, class T> \
+struct concept_name : \
+ ::boost::type_erasure::detail::choose_member_impl_t<Sig, T, \
+ boost_type_erasure_impl::concept_name##member, \
+ boost_type_erasure_impl::concept_name##self \
+ > \
+{}; \
+ \
+template<class Sig, class T> \
+::boost::type_erasure::detail::member_choose_interface<Sig, T, concept_name,\
+ boost_type_erasure_impl::concept_name ## _member_interface> \
+boost_type_erasure_find_interface(concept_name<Sig, T>);
+
+#define BOOST_TYPE_ERASURE_MEMBER_SIMPLE(name, ...) \
+ BOOST_TYPE_ERASURE_MEMBER_I(has_ ## name, name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_NS_I(concept_name, name) \
+ BOOST_TYPE_ERASURE_MEMBER_I(concept_name, name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_NS(concept_name, name) \
+ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \
+ BOOST_TYPE_ERASURE_MEMBER_NS_I(BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(concept_name)), concept_name), name) \
+ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(concept_name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_NAMED(concept_name, name, ...) \
+ BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \
+ BOOST_TYPE_ERASURE_MEMBER_NS, \
+ BOOST_TYPE_ERASURE_MEMBER_I) \
+ (concept_name, name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_CAT(x, y) x y
+
+#define BOOST_TYPE_ERASURE_MEMBER(name, ...) \
+ BOOST_TYPE_ERASURE_MEMBER_CAT( \
+ BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \
+ BOOST_TYPE_ERASURE_MEMBER_SIMPLE, \
+ BOOST_TYPE_ERASURE_MEMBER_NAMED), \
+ (name, __VA_ARGS__))
+
+#endif
+
+#endif
diff --git a/boost/type_erasure/detail/meta.hpp b/boost/type_erasure/detail/meta.hpp
new file mode 100644
index 0000000000..96e786fde6
--- /dev/null
+++ b/boost/type_erasure/detail/meta.hpp
@@ -0,0 +1,89 @@
+// Boost.TypeErasure library
+//
+// Copyright 2018 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$
+
+#ifndef BOOST_TYPE_ERASURE_DETAIL_META_HPP_INCLUDED
+#define BOOST_TYPE_ERASURE_DETAIL_META_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ /* MSVC 14.0 breaks down in the template alias quagmire. */ \
+ !BOOST_WORKAROUND(BOOST_MSVC, <= 1900)
+
+#define BOOST_TYPE_ERASURE_USE_MP11
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/mpl.hpp>
+
+namespace boost {
+namespace type_erasure {
+namespace detail {
+
+struct mp11_list_inserter
+{
+ template<class L, class T>
+ using apply = ::boost::mpl::identity< ::boost::mp11::mp_push_back<L, T> >;
+};
+
+template<class T>
+struct make_mp_list_impl
+{
+ typedef typename ::boost::mpl::fold<
+ T,
+ ::boost::mp11::mp_list<>,
+ ::boost::type_erasure::detail::mp11_list_inserter
+ >::type type;
+};
+
+template<class... T>
+struct make_mp_list_impl< ::boost::mp11::mp_list<T...> >
+{
+ typedef ::boost::mp11::mp_list<T...> type;
+};
+
+template<class T>
+using make_mp_list = typename make_mp_list_impl<T>::type;
+
+template<bool>
+struct eval_if_impl;
+
+template<>
+struct eval_if_impl<true>
+{
+ template<template<class...> class T, template<class...> class F, class... A>
+ using apply = T<A...>;
+};
+
+template<>
+struct eval_if_impl<false>
+{
+ template<template<class...> class T, template<class...> class F, class... A>
+ using apply = F<A...>;
+};
+
+template<bool B, template<class...> class T, template<class...> class F, class... A>
+using eval_if = typename ::boost::type_erasure::detail::eval_if_impl<B>::template apply<T, F, A...>;
+
+template<class T0, class...>
+using first = T0;
+
+}
+}
+}
+
+#endif
+
+#endif
diff --git a/boost/type_erasure/detail/normalize.hpp b/boost/type_erasure/detail/normalize.hpp
index a6849a6cd9..02c232a612 100644
--- a/boost/type_erasure/detail/normalize.hpp
+++ b/boost/type_erasure/detail/normalize.hpp
@@ -30,6 +30,7 @@
#include <boost/type_erasure/detail/get_placeholders.hpp>
#include <boost/type_erasure/detail/rebind_placeholders.hpp>
#include <boost/type_erasure/detail/normalize_deduced.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
#include <boost/type_erasure/relaxed.hpp>
#include <boost/type_erasure/builtin.hpp>
@@ -43,7 +44,6 @@ template<class T, class U>
struct same_type;
namespace detail {
-
struct substitution_map_tag {};
// a wrapper around an mpl::map that
@@ -87,20 +87,6 @@ struct has_key_impl< ::boost::type_erasure::detail::substitution_map_tag>
namespace type_erasure {
namespace detail {
-// given a partial substitution map from same_type,
-// resolves a placeholder as far as possible.
-template<class M, class T>
-struct resolve_same_type
-{
- typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
- ::boost::type_erasure::detail::resolve_same_type<
- M,
- typename ::boost::mpl::at<M, T>::type
- >,
- ::boost::mpl::identity<T>
- >::type type;
-};
-
// Given the arguments to same_type, determines
// which should be the key and which should be
// the value in the substitution map.
@@ -135,6 +121,22 @@ struct select_pair<
> type;
};
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
+
+// given a partial substitution map from same_type,
+// resolves a placeholder as far as possible.
+template<class M, class T>
+struct resolve_same_type
+{
+ typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
+ ::boost::type_erasure::detail::resolve_same_type<
+ M,
+ typename ::boost::mpl::at<M, T>::type
+ >,
+ ::boost::mpl::identity<T>
+ >::type type;
+};
+
// M is a map of placeholder substitutions
template<class M, class T>
struct normalize_placeholder
@@ -377,20 +379,422 @@ struct collect_concepts
Concept,
::boost::type_erasure::detail::substitution_map<Map>
>::type transformed;
+ typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence<Concept>,
+ ::boost::mpl::fold<Concept, Out, collect_concepts< ::boost::mpl::_2, Map, ::boost::mpl::_1> >,
+ ::boost::mpl::identity<Out>
+ >::type type1;
typedef typename ::boost::mpl::eval_if<
::boost::is_same<transformed, void>,
- ::boost::mpl::identity<Out>,
+ ::boost::mpl::identity<type1>,
::boost::mpl::insert<
- Out,
+ type1,
transformed
>
- >::type type1;
- typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence<Concept>,
- ::boost::mpl::fold<Concept, type1, collect_concepts< ::boost::mpl::_2, Map, ::boost::mpl::_1> >,
- ::boost::mpl::identity<type1>
>::type type;
};
+#else
+
+template<bool>
+struct resolve_same_type_impl;
+
+template<class M, class T>
+using resolve_same_type_t =
+ typename ::boost::type_erasure::detail::resolve_same_type_impl<
+ (::boost::mp11::mp_map_contains<M, T>::value)
+ >::template apply<M, T>;
+
+template<>
+struct resolve_same_type_impl<true>
+{
+ template<class M, class T>
+ using apply = ::boost::type_erasure::detail::resolve_same_type_t<
+ M,
+ ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<M, T> >
+ >;
+};
+
+template<>
+struct resolve_same_type_impl<false>
+{
+ template<class M, class T>
+ using apply = T;
+};
+
+// given a partial substitution map from same_type,
+// resolves a placeholder as far as possible.
+template<class M, class T>
+using resolve_same_type = ::boost::mpl::identity< ::boost::type_erasure::detail::resolve_same_type_t<M, T> >;
+
+
+// M is a map of placeholder substitutions
+
+template<bool>
+struct normalize_placeholder_impl;
+
+template<class M, class T>
+using normalize_placeholder_t =
+ typename ::boost::type_erasure::detail::normalize_placeholder_impl<
+ ::boost::mp11::mp_map_contains<M, T>::value
+ >::template apply<M, T>;
+
+template<>
+struct normalize_placeholder_impl<true>
+{
+ template<class M, class T>
+ using apply = ::boost::type_erasure::detail::normalize_placeholder_t<
+ M,
+ typename ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<M, T> >
+ >;
+};
+
+template<class T>
+struct normalize_deduced_impl
+{
+ template<class Map>
+ using apply = T;
+};
+
+template<template<class...> class F, class... T>
+struct normalize_deduced_impl< ::boost::type_erasure::deduced<F<T...> > >
+{
+ template<class Map>
+ using apply = typename ::boost::type_erasure::deduced<F<normalize_placeholder_t<Map, T>...> >::type;
+};
+
+template<>
+struct normalize_placeholder_impl<false>
+{
+ template<class M, class T>
+ using apply = typename ::boost::type_erasure::detail::normalize_deduced_impl<T>::template apply<M>;
+};
+
+template<class Map, class T>
+using normalize_placeholder = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_placeholder_t<Map, T> >;
+
+// Takes a mpl::map of placeholder substitutions and
+// fully resolves it. i.e. a -> b, b -> c, becomes
+// a -> c, b -> c. Also resolves deduced placeholders
+// whose arguments are all resolved.
+template<class M>
+struct create_placeholder_map
+{
+ template<class P>
+ using transform_one = ::boost::mpl::pair<
+ typename ::boost::mpl::first<P>::type,
+ ::boost::type_erasure::detail::normalize_placeholder_t<
+ M,
+ typename ::boost::mpl::second<P>::type
+ >
+ >;
+ typedef ::boost::mp11::mp_transform<
+ transform_one,
+ M
+ > type;
+};
+
+template<class M>
+using create_placeholder_map_t = typename ::boost::type_erasure::detail::create_placeholder_map<M>::type;
+
+template<class Bindings, class P, class Out, class Sub>
+struct convert_deduced
+{
+ typedef ::boost::type_erasure::detail::rebind_placeholders_in_argument_t<
+ typename P::first,
+ Bindings
+ > result1;
+ typedef ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Sub, result1> > result;
+ typedef ::boost::mp11::mp_map_insert<Out, ::boost::mpl::pair<typename P::second, result> > type;
+ BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<type, typename P::second> >, result>));
+};
+
+template<class Bindings, class Sub>
+struct convert_deduced_f
+{
+ template<class Out, class P>
+ using apply = typename ::boost::type_erasure::detail::convert_deduced<Bindings, P, Out, Sub>::type;
+};
+
+template<class Bindings, class M, class Sub>
+using convert_deductions_t =
+ ::boost::mp11::mp_fold<
+ M,
+ ::boost::type_erasure::detail::make_mp_list<Bindings>,
+ ::boost::type_erasure::detail::convert_deduced_f<Bindings, Sub>::template apply
+ >;
+
+template<class Bindings, class M, class Sub>
+using convert_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::convert_deductions_t<Bindings, M, Sub> >;
+
+template<class Bindings, class P, class Out>
+struct add_deduced
+{
+ typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
+ typename P::first,
+ Bindings
+ >::type result;
+ typedef ::boost::mp11::mp_map_insert<Out, ::boost::mpl::pair<typename P::second, result> > type;
+ BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<type, typename P::second> >, result>));
+};
+
+template<class Bindings>
+struct add_deduced_f
+{
+ template<class Out, class P>
+ using apply = typename ::boost::type_erasure::detail::add_deduced<Bindings, P, Out>::type;
+};
+
+template<class Bindings, class M>
+using add_deductions_t =
+ ::boost::mp11::mp_fold<
+ M,
+ ::boost::type_erasure::detail::make_mp_list<Bindings>,
+ ::boost::type_erasure::detail::add_deduced_f<
+ ::boost::type_erasure::detail::make_mp_list<Bindings>
+ >::template apply
+ >;
+
+template<class Bindings, class M>
+using add_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::add_deductions_t<Bindings, M> >;
+
+// Fold Op for normalize_concept_impl
+template<class T>
+struct insert_concept_impl
+{
+ template<class Out>
+ using apply =
+ ::boost::mpl::pair<
+ ::boost::mp11::mp_set_push_back<typename Out::first, T>,
+ typename Out::second
+ >;
+};
+
+template<class Map, class T>
+using mpl_insert = typename ::boost::mpl::insert<Map, T>::type;
+
+template<class T1, class T2, class Out>
+using insert_concept_same_type =
+ ::boost::mpl::pair<
+ typename Out::first,
+ typename ::boost::type_erasure::detail::eval_if<
+ ::boost::is_same<T1, T2>::value,
+ ::boost::type_erasure::detail::first,
+ ::boost::mp11::mp_map_insert, // FIXME: is this supposed to be a replace?
+ typename Out::second,
+ typename ::boost::type_erasure::detail::select_pair<
+ T1,
+ T2
+ >::type
+ >
+ >;
+
+template<class T, class U>
+struct insert_concept_impl< ::boost::type_erasure::same_type<T, U> >
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::insert_concept_same_type<
+ ::boost::type_erasure::detail::resolve_same_type_t<
+ typename Out::second,
+ T
+ >,
+ ::boost::type_erasure::detail::resolve_same_type_t<
+ typename Out::second,
+ U
+ >,
+ Out
+ >;
+};
+
+template<bool>
+struct normalize_concept_impl_test;
+
+template<class Out, class Concept>
+using normalize_concept_impl_f =
+ typename ::boost::type_erasure::detail::normalize_concept_impl_test<
+ ::boost::mpl::is_sequence<Concept>::value
+ >::template apply<Out, Concept>;
+
+template<>
+struct normalize_concept_impl_test<true>
+{
+ template<class Out, class Concept>
+ using apply =
+ ::boost::mp11::mp_fold<
+ ::boost::type_erasure::detail::make_mp_list<Concept>,
+ Out,
+ ::boost::type_erasure::detail::normalize_concept_impl_f
+ >;
+};
+
+template<>
+struct normalize_concept_impl_test<false>
+{
+ template<class Out, class Concept>
+ using apply = typename ::boost::type_erasure::detail::insert_concept_impl<Concept>::template apply<Out>;
+};
+
+template<class Concept>
+using normalize_concept_impl_t =
+ ::boost::type_erasure::detail::normalize_concept_impl_f<
+ ::boost::mpl::pair< ::boost::mp11::mp_list<>, ::boost::mp11::mp_list<> >,
+ Concept
+ >;
+
+template<class Concept>
+using normalize_concept_impl = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_impl_t<Concept> >;
+
+template<class S, class T>
+using get_all_placeholders_impl = typename ::boost::type_erasure::detail::get_placeholders<T, S>::type;
+
+template<class Seq>
+using get_all_placeholders =
+ ::boost::mp11::mp_fold<
+ Seq,
+ ::boost::mp11::mp_list<>,
+ ::boost::type_erasure::detail::get_all_placeholders_impl
+ >;
+
+template<class T>
+using make_identity_pair = ::boost::mpl::pair<T, T>;
+
+template<class Concept>
+using make_identity_placeholder_map =
+ ::boost::mp11::mp_transform<
+ ::boost::type_erasure::detail::make_identity_pair,
+ ::boost::type_erasure::detail::get_all_placeholders<
+ typename normalize_concept_impl_t<Concept>::first
+ >
+ >;
+
+template<class S, class T>
+using append_type_info = ::boost::mp11::mp_set_push_back<
+ S,
+ ::boost::type_erasure::typeid_<T>
+>;
+
+template<class Seq>
+using add_typeinfo_t =
+ ::boost::mp11::mp_fold<
+ get_all_placeholders<Seq>,
+ Seq,
+ ::boost::type_erasure::detail::append_type_info
+ >;
+
+// Seq should be a flattened mp_list sequence of leaf concepts.
+// adds typeid_<P> for every placeholder used.
+template<class Seq>
+using add_typeinfo = ::boost::mpl::identity<add_typeinfo_t<Seq> >;
+
+template<class Substitutions>
+struct normalize_concept_substitute_f
+{
+ template<class Set, class Concept>
+ using apply = ::boost::mp11::mp_set_push_back<Set,
+ typename ::boost::type_erasure::detail::rebind_placeholders<
+ Concept,
+ Substitutions
+ >::type
+ >;
+};
+
+template<class Concept, class Pair>
+using normalize_concept_adjustments =
+ ::boost::type_erasure::detail::eval_if<
+ ::boost::type_erasure::is_relaxed<Concept>::value,
+ ::boost::type_erasure::detail::add_typeinfo_t,
+ ::boost::type_erasure::detail::first,
+ ::boost::mp11::mp_fold<
+ typename Pair::first,
+ ::boost::mp11::mp_list<>,
+ ::boost::type_erasure::detail::normalize_concept_substitute_f<
+ ::boost::type_erasure::detail::create_placeholder_map_t<
+ typename Pair::second
+ >
+ >::template apply
+ >
+ >;
+
+template<class Concept>
+using get_placeholder_normalization_map_t =
+ ::boost::type_erasure::detail::create_placeholder_map_t<
+ typename normalize_concept_impl_t<Concept>::second
+ >;
+
+template<class Concept>
+using get_placeholder_normalization_map =
+ ::boost::type_erasure::detail::create_placeholder_map<
+ typename normalize_concept_impl_t<Concept>::second
+ >;
+
+// Flattens a Concept to an mpl::vector of primitive
+// concepts. Resolves same_type and deduced placeholders.
+template<class Concept>
+using normalize_concept_t =
+ ::boost::type_erasure::detail::normalize_concept_adjustments<
+ Concept,
+ boost::type_erasure::detail::normalize_concept_impl_t<Concept>
+ >;
+
+template<class Concept>
+using normalize_concept = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_t<Concept> >;
+
+template<class Map>
+struct collect_concepts_f;
+
+template<class Out, class Concept, class Map>
+using collect_concepts_recursive = ::boost::mp11::mp_fold<
+ ::boost::type_erasure::detail::make_mp_list<Concept>,
+ Out,
+ ::boost::type_erasure::detail::collect_concepts_f<Map>::template apply
+>;
+
+template<class Concept, class Map, class Out, class Transformed>
+using collect_concepts_impl =
+ ::boost::type_erasure::detail::eval_if< ::boost::is_same<Transformed, void>::value,
+ ::boost::type_erasure::detail::first,
+ ::boost::mp11::mp_set_push_front,
+ ::boost::type_erasure::detail::eval_if< ::boost::mpl::is_sequence<Concept>::value,
+ ::boost::type_erasure::detail::collect_concepts_recursive,
+ ::boost::type_erasure::detail::first,
+ Out,
+ Concept,
+ Map
+ >,
+ Transformed
+ >;
+
+template<class Concept,
+ class Map = ::boost::type_erasure::detail::create_placeholder_map_t<
+ typename ::boost::type_erasure::detail::normalize_concept_impl_t<
+ Concept
+ >::second
+ >,
+ class Out = ::boost::mp11::mp_list<>
+>
+using collect_concepts_t =
+ collect_concepts_impl<Concept, Map, Out,
+ typename ::boost::type_erasure::detail::rebind_placeholders<
+ Concept,
+ Map
+ >::type
+ >;
+
+template<class Map>
+struct collect_concepts_f
+{
+ template<class Out, class Concept>
+ using apply = ::boost::type_erasure::detail::collect_concepts_t<Concept, Map, Out>;
+};
+
+// Returns an MPL sequence containing all the concepts
+// in Concept. If Concept is considered as a DAG,
+// the result will be sorted topologically.
+template<class Concept>
+using collect_concepts = ::boost::mpl::identity<
+ ::boost::type_erasure::detail::collect_concepts_t<Concept> >;
+
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/normalize_deduced.hpp b/boost/type_erasure/detail/normalize_deduced.hpp
index 83d0d3b25b..dcf3fd3625 100644
--- a/boost/type_erasure/detail/normalize_deduced.hpp
+++ b/boost/type_erasure/detail/normalize_deduced.hpp
@@ -16,6 +16,9 @@
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
+
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
namespace boost {
namespace type_erasure {
@@ -36,6 +39,8 @@ struct normalize_placeholder;
#endif
+#endif
+
#else
#define N BOOST_PP_ITERATION()
diff --git a/boost/type_erasure/detail/null.hpp b/boost/type_erasure/detail/null.hpp
index ef977f4254..e0c3173704 100644
--- a/boost/type_erasure/detail/null.hpp
+++ b/boost/type_erasure/detail/null.hpp
@@ -13,6 +13,7 @@
#ifndef BOOST_TYPE_ERASURE_DETAIL_NULL_HPP_INCLUDED
#define BOOST_TYPE_ERASURE_DETAIL_NULL_HPP_INCLUDED
+#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
@@ -34,10 +35,23 @@ struct get_null_vtable_entry {
typename ::boost::remove_pointer<typename Concept::type>::type> type;
};
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/null.hpp>
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY)
#include BOOST_PP_ITERATE()
+#else
+
+template<class R, class... T>
+struct null_throw<R(T...)> {
+ static R value(T...) {
+ BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_function_call());
+ }
+};
+
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/rebind_placeholders.hpp b/boost/type_erasure/detail/rebind_placeholders.hpp
index d93d429c5d..0d0ef7c8e4 100644
--- a/boost/type_erasure/detail/rebind_placeholders.hpp
+++ b/boost/type_erasure/detail/rebind_placeholders.hpp
@@ -26,6 +26,7 @@
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/type_erasure/config.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
#include <boost/type_erasure/is_placeholder.hpp>
namespace boost {
@@ -48,6 +49,132 @@ struct identity
typedef T type;
};
+template<class PrimitiveConcept, class Sig>
+struct vtable_adapter;
+
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class T, class Bindings>
+using rebind_placeholders_t = typename rebind_placeholders<T, Bindings>::type;
+
+template<class T, class Bindings>
+using rebind_one_placeholder = ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Bindings, T> >;
+
+template<class T>
+struct rebind_placeholders_in_argument_impl
+{
+ template<class Bindings>
+ using apply = ::boost::type_erasure::detail::eval_if<
+ ::boost::mp11::mp_map_contains<Bindings, T>::value,
+ ::boost::type_erasure::detail::rebind_one_placeholder,
+ ::boost::type_erasure::detail::first,
+ T,
+ Bindings
+ >;
+};
+
+template<class T, class Bindings>
+using rebind_placeholders_in_argument_t = typename ::boost::type_erasure::detail::rebind_placeholders_in_argument_impl<T>::template apply<Bindings>;
+
+template<class T, class Bindings>
+using rebind_placeholders_in_argument = ::boost::mpl::identity< ::boost::type_erasure::detail::rebind_placeholders_in_argument_t<T, Bindings> >;
+
+template<class T>
+struct rebind_placeholders_in_argument_impl<T&>
+{
+ template<class Bindings>
+ using apply = rebind_placeholders_in_argument_t<T, Bindings>&;
+};
+
+template<class T>
+struct rebind_placeholders_in_argument_impl<T&&>
+{
+ template<class Bindings>
+ using apply = rebind_placeholders_in_argument_t<T, Bindings>&&;
+};
+
+template<class T>
+struct rebind_placeholders_in_argument_impl<const T>
+{
+ template<class Bindings>
+ using apply = rebind_placeholders_in_argument_t<T, Bindings> const;
+};
+
+template<class F, class Bindings>
+using rebind_placeholders_in_deduced =
+ typename ::boost::type_erasure::deduced<
+ ::boost::type_erasure::detail::rebind_placeholders_t<F, Bindings>
+ >::type;
+
+template<class F, class Bindings>
+using rebind_deduced_placeholder =
+ ::boost::mp11::mp_second<
+ ::boost::mp11::mp_map_find<Bindings, ::boost::type_erasure::deduced<F> >
+ >;
+
+template<class F>
+struct rebind_placeholders_in_argument_impl<
+ ::boost::type_erasure::deduced<F>
+>
+{
+ template<class Bindings>
+ using apply = ::boost::type_erasure::detail::eval_if<
+ ::boost::mp11::mp_map_contains<Bindings, ::boost::type_erasure::deduced<F> >::value,
+ ::boost::type_erasure::detail::rebind_deduced_placeholder,
+ ::boost::type_erasure::detail::rebind_placeholders_in_deduced,
+ F,
+ Bindings
+ >;
+};
+
+template<class R, class... T>
+struct rebind_placeholders_in_argument_impl<R(T...)>
+{
+ template<class Bindings>
+ using apply =
+ rebind_placeholders_in_argument_t<R, Bindings>
+ (rebind_placeholders_in_argument_t<T, Bindings>...);
+};
+
+template<class R, class C, class... T>
+struct rebind_placeholders_in_argument_impl<R (C::*)(T...)>
+{
+ template<class Bindings>
+ using apply =
+ rebind_placeholders_in_argument_t<R, Bindings>
+ (rebind_placeholders_in_argument_t<C, Bindings>::*)
+ (rebind_placeholders_in_argument_t<T, Bindings>...);
+};
+
+template<class R, class C, class... T>
+struct rebind_placeholders_in_argument_impl<R (C::*)(T...) const>
+{
+ template<class Bindings>
+ using apply =
+ rebind_placeholders_in_argument_t<R, Bindings>
+ (rebind_placeholders_in_argument_t<C, Bindings>::*)
+ (rebind_placeholders_in_argument_t<T, Bindings>...) const;
+};
+
+template<template<class...> class T, class... U, class Bindings>
+struct rebind_placeholders<T<U...>, Bindings>
+{
+ typedef ::boost::type_erasure::detail::make_mp_list<Bindings> xBindings;
+ typedef T<rebind_placeholders_in_argument_t<U, xBindings>...> type;
+};
+
+template<class PrimitiveConcept, class Sig, class Bindings>
+struct rebind_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Bindings>
+{
+ typedef ::boost::type_erasure::detail::make_mp_list<Bindings> xBindings;
+ typedef vtable_adapter<
+ rebind_placeholders_t<PrimitiveConcept, xBindings>,
+ rebind_placeholders_in_argument_t<Sig, xBindings>
+ > type;
+};
+
+#else
+
template<class T, class Bindings>
struct rebind_placeholders_in_argument
{
@@ -62,6 +189,15 @@ struct rebind_placeholders_in_argument
>::type type;
};
+template<class PrimitiveConcept, class Sig, class Bindings>
+struct rebind_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Bindings>
+{
+ typedef vtable_adapter<
+ typename rebind_placeholders<PrimitiveConcept, Bindings>::type,
+ typename rebind_placeholders_in_argument<Sig, Bindings>::type
+ > type;
+};
+
template<class T, class Bindings>
struct rebind_placeholders_in_argument<T&, Bindings>
{
@@ -134,6 +270,26 @@ struct rebind_placeholders_in_argument<R(T...), Bindings>
>::type type(typename rebind_placeholders_in_argument<T, Bindings>::type...);
};
+template<class R, class C, class... T, class Bindings>
+struct rebind_placeholders_in_argument<R (C::*)(T...), Bindings>
+{
+ typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
+ R,
+ Bindings
+ >::type (rebind_placeholders_in_argument<C, Bindings>::type::*type)
+ (typename rebind_placeholders_in_argument<T, Bindings>::type...);
+};
+
+template<class R, class C, class... T, class Bindings>
+struct rebind_placeholders_in_argument<R (C::*)(T...) const, Bindings>
+{
+ typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
+ R,
+ Bindings
+ >::type (rebind_placeholders_in_argument<C, Bindings>::type::*type)
+ (typename rebind_placeholders_in_argument<T, Bindings>::type...) const;
+};
+
#else
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/rebind_placeholders.hpp>
@@ -142,6 +298,8 @@ struct rebind_placeholders_in_argument<R(T...), Bindings>
#endif
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/storage.hpp b/boost/type_erasure/detail/storage.hpp
index 8f8bf865ea..8e572871f3 100644
--- a/boost/type_erasure/detail/storage.hpp
+++ b/boost/type_erasure/detail/storage.hpp
@@ -13,7 +13,7 @@
#include <boost/config.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/decay.hpp>
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# include <utility> // for std::forward, std::move
@@ -37,11 +37,10 @@ struct storage
storage(storage&& other) : data(other.data) {}
storage& operator=(const storage& other) { data = other.data; return *this; }
template<class T>
- explicit storage(T&& arg) : data(new typename remove_cv<
- typename remove_reference<T>::type>::type(std::forward<T>(arg))) {}
+ explicit storage(T&& arg) : data(new typename boost::decay<T>::type(std::forward<T>(arg))) {}
#else
template<class T>
- explicit storage(const T& arg) : data(new T(arg)) {}
+ explicit storage(const T& arg) : data(new typename boost::decay<T>::type(arg)) {}
#endif
void* data;
};
diff --git a/boost/type_erasure/detail/vtable.hpp b/boost/type_erasure/detail/vtable.hpp
index b30a15a061..965ffcb390 100644
--- a/boost/type_erasure/detail/vtable.hpp
+++ b/boost/type_erasure/detail/vtable.hpp
@@ -17,6 +17,7 @@
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/expr_if.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
@@ -98,7 +99,7 @@ struct compare_vtable;
template<>
struct compare_vtable<> {
template<class S>
- static bool apply(const S& s1, const S& s2)
+ static bool apply(const S& /*s1*/, const S& /*s2*/)
{
return true;
}
@@ -151,9 +152,9 @@ struct vtable_storage<>
vtable_storage() = default;
template<class Bindings, class Src>
- void convert_from(const Src& src) {}
+ void convert_from(const Src& /*src*/) {}
- bool operator==(const vtable_storage& other) const
+ bool operator==(const vtable_storage& /*other*/) const
{ return true; }
};
@@ -249,12 +250,12 @@ struct BOOST_PP_CAT(vtable_storage, N)
BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_ENTRY, ~)
template<class Bindings, class Src>
- void convert_from(const Src& src)
+ void convert_from(const Src& BOOST_PP_EXPR_IF(N, src))
{
BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_CONVERT_ELEMENT, ~)
}
- bool operator==(const BOOST_PP_CAT(vtable_storage, N)& other) const
+ bool operator==(const BOOST_PP_CAT(vtable_storage, N)& BOOST_PP_EXPR_IF(N, other)) const
{ return true BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_COMPARE, ~); }
};