diff options
Diffstat (limited to 'boost/type_erasure/detail')
-rw-r--r-- | boost/type_erasure/detail/access.hpp | 105 | ||||
-rw-r--r-- | boost/type_erasure/detail/adapt_to_vtable.hpp | 19 | ||||
-rw-r--r-- | boost/type_erasure/detail/any_base.hpp | 4 | ||||
-rw-r--r-- | boost/type_erasure/detail/check_call.hpp | 72 | ||||
-rw-r--r-- | boost/type_erasure/detail/check_map.hpp | 50 | ||||
-rw-r--r-- | boost/type_erasure/detail/dynamic_vtable.hpp | 22 | ||||
-rw-r--r-- | boost/type_erasure/detail/extract_concept.hpp | 32 | ||||
-rw-r--r-- | boost/type_erasure/detail/get_placeholders.hpp | 102 | ||||
-rw-r--r-- | boost/type_erasure/detail/instantiate.hpp | 60 | ||||
-rw-r--r-- | boost/type_erasure/detail/member11.hpp | 214 | ||||
-rw-r--r-- | boost/type_erasure/detail/meta.hpp | 89 | ||||
-rw-r--r-- | boost/type_erasure/detail/normalize.hpp | 446 | ||||
-rw-r--r-- | boost/type_erasure/detail/normalize_deduced.hpp | 5 | ||||
-rw-r--r-- | boost/type_erasure/detail/null.hpp | 14 | ||||
-rw-r--r-- | boost/type_erasure/detail/rebind_placeholders.hpp | 158 | ||||
-rw-r--r-- | boost/type_erasure/detail/storage.hpp | 7 | ||||
-rw-r--r-- | boost/type_erasure/detail/vtable.hpp | 11 |
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, ~); } }; |