From b8cf34c691623e4ec329053cbbf68522a855882d Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Thu, 5 Dec 2019 15:12:59 +0900 Subject: Imported Upstream version 1.67.0 --- boost/type_erasure/any.hpp | 1114 ++++++++++++++++++--- boost/type_erasure/any_cast.hpp | 2 +- boost/type_erasure/builtin.hpp | 46 +- boost/type_erasure/call.hpp | 49 + boost/type_erasure/check_match.hpp | 46 +- boost/type_erasure/concept_of.hpp | 13 + boost/type_erasure/constructible.hpp | 6 +- boost/type_erasure/deduced.hpp | 4 + boost/type_erasure/derived.hpp | 7 + boost/type_erasure/detail/access.hpp | 105 +- boost/type_erasure/detail/adapt_to_vtable.hpp | 19 +- boost/type_erasure/detail/any_base.hpp | 4 +- boost/type_erasure/detail/check_call.hpp | 72 +- boost/type_erasure/detail/check_map.hpp | 50 +- boost/type_erasure/detail/dynamic_vtable.hpp | 22 +- boost/type_erasure/detail/extract_concept.hpp | 32 +- boost/type_erasure/detail/get_placeholders.hpp | 102 +- boost/type_erasure/detail/instantiate.hpp | 60 ++ boost/type_erasure/detail/member11.hpp | 214 ++++ boost/type_erasure/detail/meta.hpp | 89 ++ boost/type_erasure/detail/normalize.hpp | 446 ++++++++- boost/type_erasure/detail/normalize_deduced.hpp | 5 + boost/type_erasure/detail/null.hpp | 14 + boost/type_erasure/detail/rebind_placeholders.hpp | 158 +++ boost/type_erasure/detail/storage.hpp | 7 +- boost/type_erasure/detail/vtable.hpp | 11 +- boost/type_erasure/dynamic_any_cast.hpp | 10 +- boost/type_erasure/free.hpp | 242 ++++- boost/type_erasure/is_placeholder.hpp | 17 +- boost/type_erasure/is_subconcept.hpp | 66 +- boost/type_erasure/member.hpp | 71 +- boost/type_erasure/operators.hpp | 3 - boost/type_erasure/param.hpp | 51 +- boost/type_erasure/placeholder.hpp | 5 +- boost/type_erasure/placeholder_of.hpp | 11 + boost/type_erasure/rebind_any.hpp | 10 + boost/type_erasure/register_binding.hpp | 14 +- boost/type_erasure/relaxed.hpp | 2 +- boost/type_erasure/require_match.hpp | 23 + boost/type_erasure/static_binding.hpp | 2 +- 40 files changed, 2919 insertions(+), 305 deletions(-) create mode 100644 boost/type_erasure/detail/member11.hpp create mode 100644 boost/type_erasure/detail/meta.hpp (limited to 'boost/type_erasure') diff --git a/boost/type_erasure/any.hpp b/boost/type_erasure/any.hpp index 3ed0243498..2505c96908 100644 --- a/boost/type_erasure/any.hpp +++ b/boost/type_erasure/any.hpp @@ -12,6 +12,9 @@ #define BOOST_TYPE_ERASURE_ANY_HPP_INCLUDED #include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +# include // std::forward, std::move +#endif #include #include #include @@ -20,7 +23,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -44,9 +48,18 @@ #include #include +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4355) +#pragma warning(disable:4521) +#pragma warning(disable:4522) // multiple assignment operators specified +#endif + namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN + template struct constructible; @@ -56,17 +69,48 @@ struct destructible; template struct assignable; +#endif + namespace detail { +#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template +struct choose_concept_interface +{ + typedef ::boost::type_erasure::concept_interface type; +}; + +#else + +struct default_concept_interface +{ + template + using apply = ::boost::type_erasure::concept_interface; +}; + +default_concept_interface boost_type_erasure_find_interface(...); + +template +struct choose_concept_interface +{ + typedef decltype(boost_type_erasure_find_interface(::boost::declval())) finder; + typedef typename finder::template apply type; +}; + +#endif + +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + template struct compute_bases { - typedef typename ::boost::mpl::fold< + typedef typename ::boost::mpl::reverse_fold< typename ::boost::type_erasure::detail::collect_concepts< Concept >::type, ::boost::type_erasure::any_base, - ::boost::type_erasure::concept_interface< + ::boost::type_erasure::detail::choose_concept_interface< ::boost::mpl::_2, ::boost::mpl::_1, T @@ -74,6 +118,30 @@ struct compute_bases >::type type; }; +#else + +template +struct compute_bases_f +{ + template + using apply = typename ::boost::type_erasure::detail::choose_concept_interface::type; +}; + +template +using compute_bases_t = + ::boost::mp11::mp_reverse_fold< + typename ::boost::type_erasure::detail::collect_concepts_t< + Concept + >, + ::boost::type_erasure::any_base, + ::boost::type_erasure::detail::compute_bases_f::template apply + >; + +template +using compute_bases = ::boost::mpl::identity< ::boost::type_erasure::detail::compute_bases_t >; + +#endif + template T make(T*) { return T(); } @@ -90,6 +158,22 @@ no check_overload(const void*); struct fallback {}; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template +fallback make_fallback(T&&, boost::mpl::false_) +{ + return fallback(); +} + +template +T&& make_fallback(T&& arg, boost::mpl::true_) +{ + return std::forward(arg); +} + +#else + template fallback make_fallback(const T&, boost::mpl::false_) { @@ -102,19 +186,469 @@ const T& make_fallback(const T& arg, boost::mpl::true_) return arg; } +#endif + template struct is_any : ::boost::mpl::false_ {}; template struct is_any > : ::boost::mpl::true_ {}; +#ifdef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + +template +struct has_constructor : + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval(). + _boost_type_erasure_deduce_constructor(::boost::declval()...) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + > +{}; + +template +using has_copy_constructor = + ::boost::type_erasure::is_subconcept< + ::boost::type_erasure::constructible< + typename ::boost::type_erasure::placeholder_of::type(typename ::boost::type_erasure::placeholder_of::type const&) + >, + typename ::boost::type_erasure::concept_of::type + >; + +template +using has_move_constructor = + ::boost::type_erasure::is_subconcept< + ::boost::type_erasure::constructible< + typename ::boost::type_erasure::placeholder_of::type(typename ::boost::type_erasure::placeholder_of::type &&) + >, + typename ::boost::type_erasure::concept_of::type + >; + +template +using has_mutable_copy_constructor = + ::boost::type_erasure::is_subconcept< + ::boost::type_erasure::constructible< + typename ::boost::type_erasure::placeholder_of::type(typename ::boost::type_erasure::placeholder_of::type &) + >, + typename ::boost::type_erasure::concept_of::type + >; + +struct empty {}; + +template +struct is_binding_arg : ::boost::mpl::false_ {}; +template +struct is_binding_arg > : ::boost::mpl::true_ {}; +template +struct is_binding_arg&&> : ::boost::mpl::true_ {}; +template +struct is_binding_arg&> : ::boost::mpl::true_ {}; +template +struct is_binding_arg const&> : ::boost::mpl::true_ {}; + +template +struct is_static_binding_arg : ::boost::mpl::false_ {}; +template +struct is_static_binding_arg > : ::boost::mpl::true_ {}; +template +struct is_static_binding_arg&&> : ::boost::mpl::true_ {}; +template +struct is_static_binding_arg&> : ::boost::mpl::true_ {}; +template +struct is_static_binding_arg const&> : ::boost::mpl::true_ {}; + +template +struct is_any_arg : ::boost::mpl::false_ {}; +template +struct is_any_arg > : ::boost::mpl::true_ {}; +template +struct is_any_arg&&> : ::boost::mpl::true_ {}; +template +struct is_any_arg&> : ::boost::mpl::true_ {}; +template +struct is_any_arg const&> : ::boost::mpl::true_ {}; + +template +struct safe_concept_of; +template +struct safe_concept_of > { typedef Concept type; }; +template +struct safe_concept_of&&> { typedef Concept type; }; +template +struct safe_concept_of&> { typedef Concept type; }; +template +struct safe_concept_of const&> { typedef Concept type; }; + +template +struct safe_placeholder_of; +template +struct safe_placeholder_of > { typedef T type; }; +template +struct safe_placeholder_of&&> { typedef T type; }; +template +struct safe_placeholder_of&> { typedef T type; }; +template +struct safe_placeholder_of const&> { typedef T type; }; + +template +using safe_placeholder_t = ::boost::remove_cv_t< ::boost::remove_reference_t::type> >; + } -#ifdef BOOST_MSVC -#pragma warning(push) -#pragma warning(disable:4355) -#pragma warning(disable:4521) +// Enables or deletes the copy/move constructors depending on the Concept. +template +struct any_constructor_control : Base +{ + using Base::Base; +}; + +template +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor::value && + ::boost::type_erasure::detail::has_move_constructor::value && + ::boost::type_erasure::detail::has_mutable_copy_constructor::value + >::type +> : Base +{ + using Base::Base; + any_constructor_control() = default; + any_constructor_control(any_constructor_control&) = default; + any_constructor_control(any_constructor_control&&) = default; + any_constructor_control& operator=(any_constructor_control const& other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor::value && + !::boost::type_erasure::detail::has_move_constructor::value && + ::boost::type_erasure::detail::has_mutable_copy_constructor::value + >::type +> : Base +{ + using Base::Base; + any_constructor_control() = default; + any_constructor_control(any_constructor_control&) = default; + any_constructor_control(any_constructor_control&&) = delete; + any_constructor_control& operator=(any_constructor_control const& other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor::value && + ::boost::type_erasure::detail::has_move_constructor::value && + !::boost::type_erasure::detail::has_mutable_copy_constructor::value + >::type +> : Base +{ + using Base::Base; + any_constructor_control() = default; + any_constructor_control(any_constructor_control const&) = delete; + any_constructor_control(any_constructor_control&&) = default; + any_constructor_control& operator=(any_constructor_control const& other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor::value && + !::boost::type_erasure::detail::has_move_constructor::value && + !::boost::type_erasure::detail::has_mutable_copy_constructor::value + >::type +> : Base +{ + using Base::Base; + any_constructor_control() = default; + any_constructor_control(any_constructor_control const&) = delete; + any_constructor_control(any_constructor_control&&) = delete; + any_constructor_control& operator=(any_constructor_control const& other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast(*this) = static_cast(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template +struct any_constructor_impl : + ::boost::type_erasure::detail::compute_bases< + ::boost::type_erasure::any, + Concept, + T + >::type +{ + typedef typename ::boost::type_erasure::detail::compute_bases< + ::boost::type_erasure::any, + Concept, + T + >::type _boost_type_erasure_base; + // Internal constructors + typedef ::boost::type_erasure::binding _boost_type_erasure_table_type; + any_constructor_impl(const ::boost::type_erasure::detail::storage& data_arg, const _boost_type_erasure_table_type& table_arg) + : _boost_type_erasure_table(table_arg), + _boost_type_erasure_data(data_arg) + {} + any_constructor_impl(::boost::type_erasure::detail::storage&& data_arg, const _boost_type_erasure_table_type& table_arg) + : _boost_type_erasure_table(table_arg), + _boost_type_erasure_data(data_arg) + {} + // default constructor + any_constructor_impl() + { + BOOST_MPL_ASSERT((::boost::type_erasure::is_relaxed)); + _boost_type_erasure_data.data = 0; + } + // capturing constructor + template::value && + !::boost::type_erasure::detail::is_binding_arg::value && + !::boost::type_erasure::detail::is_static_binding_arg::value + >::type* = nullptr + > + any_constructor_impl(U&& data_arg) + : _boost_type_erasure_table(( + BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, ::boost::decay_t), + ::boost::type_erasure::make_binding< + ::boost::mpl::map1< ::boost::mpl::pair > > + >() + )), + _boost_type_erasure_data(std::forward(data_arg)) + {} + template::value && + !::boost::type_erasure::detail::is_binding_arg::value && + !::boost::type_erasure::detail::is_static_binding_arg::value + >::type* = nullptr + > + any_constructor_impl(U&& data_arg, const static_binding& b) + : _boost_type_erasure_table(( + BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map), + b + )), + _boost_type_erasure_data(std::forward(data_arg)) + { + BOOST_MPL_ASSERT((::boost::is_same< + typename ::boost::mpl::at::type, ::boost::decay_t >)); + } + // converting constructor + template::type, + typename ::boost::mpl::if_c< ::boost::is_same >::value, + void, + ::boost::mpl::map1< + ::boost::mpl::pair > + > + >::type + >::value + >::type* = nullptr + > + any_constructor_impl(U&& other) + : _boost_type_erasure_table( + ::boost::type_erasure::detail::access::table(other), + typename ::boost::mpl::if_c< ::boost::is_same >::value, +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + ::boost::type_erasure::detail::substitution_map< ::boost::mpl::map0<> >, +#else + ::boost::type_erasure::detail::make_identity_placeholder_map, #endif + ::boost::mpl::map1< + ::boost::mpl::pair< + T, + ::boost::type_erasure::detail::safe_placeholder_t + > + > + >::type() + ), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor(std::forward(other)) : 0 + ), std::forward(other)) + ) + {} + template::value + >::type* = nullptr + > + any_constructor_impl(U&& other, const binding& binding_arg) + : _boost_type_erasure_table(binding_arg), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor(std::forward(other)) : 0 + ), std::forward(other)) + ) + {} + template::type, + Map + >::value + >::type* = nullptr + > + any_constructor_impl(U&& other, const static_binding& binding_arg) + : _boost_type_erasure_table(::boost::type_erasure::detail::access::table(other), binding_arg), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor(std::forward(other)) : 0 + ), std::forward(other)) + ) + {} + // copy and move constructors are a special case of the converting + // constructors, but must be defined separately to keep C++ happy. + any_constructor_impl(const any_constructor_impl& other) + : _boost_type_erasure_table( + ::boost::type_erasure::detail::access::table(other) + ), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor( + static_cast(other)) : 0 + ), other) + ) + {} + any_constructor_impl(any_constructor_impl& other) + : _boost_type_erasure_table( + ::boost::type_erasure::detail::access::table(other) + ), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor( + static_cast(other)) : 0 + ), other) + ) + {} + any_constructor_impl(any_constructor_impl&& other) + : _boost_type_erasure_table( + ::boost::type_erasure::detail::access::table(other) + ), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor( + static_cast(other)) : 0 + ), std::move(other)) + ) + {} + + template + const _boost_type_erasure_table_type& _boost_type_erasure_extract_table( + ::boost::type_erasure::constructible*, + U&&... u) + { + return *::boost::type_erasure::detail::extract_table(static_cast(0), u...); + } + // forwarding constructor + template::value + >::type* = nullptr + > + explicit any_constructor_impl(U&&... u) + : _boost_type_erasure_table( + _boost_type_erasure_extract_table( + false? this->_boost_type_erasure_deduce_constructor(std::forward(u)...) : 0, + std::forward(u)... + ) + ), + _boost_type_erasure_data( + ::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? this->_boost_type_erasure_deduce_constructor(std::forward(u)...) : 0 + ), + std::forward(u)... + ) + ) + {} + template::value + >::type* = nullptr + > + explicit any_constructor_impl(const binding& binding_arg, U&&... u) + : _boost_type_erasure_table(binding_arg), + _boost_type_erasure_data( + ::boost::type_erasure::call( + binding_arg, + ::boost::type_erasure::detail::make( + false? this->_boost_type_erasure_deduce_constructor(std::forward(u)...) : 0 + ), + std::forward(u)... + ) + ) + {} + + // The assignment operator and destructor must be defined here rather + // than in any to avoid implicitly deleting the move constructor. + + any_constructor_impl& operator=(const any_constructor_impl& other) + { + static_cast(this)->_boost_type_erasure_resolve_assign( + static_cast(other)); + return *this; + } + + any_constructor_impl& operator=(any_constructor_impl& other) + { + static_cast(this)->_boost_type_erasure_resolve_assign( + static_cast(other)); + return *this; + } + + any_constructor_impl& operator=(any_constructor_impl&& other) + { + static_cast(this)->_boost_type_erasure_resolve_assign( + static_cast(other)); + return *this; + } + + ~any_constructor_impl() + { + _boost_type_erasure_table.template find< + ::boost::type_erasure::destructible + >()(_boost_type_erasure_data); + } + +protected: + friend struct ::boost::type_erasure::detail::access; + + _boost_type_erasure_table_type _boost_type_erasure_table; + ::boost::type_erasure::detail::storage _boost_type_erasure_data; +}; + +namespace detail { + +#endif + +template +struct is_rvalue_for_any : + ::boost::mpl::not_< + ::boost::is_lvalue_reference + > +{}; + +template +struct is_rvalue_for_any > : + ::boost::mpl::not_< + ::boost::is_lvalue_reference

+ > +{}; + +} /** * The class template @ref any can store any object that @@ -129,16 +663,37 @@ struct is_any > : ::boost::mpl::true_ {}; */ template class any : +#ifdef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + public ::boost::type_erasure::any_constructor_control< + ::boost::type_erasure::any_constructor_impl< + + Concept, + T + > + > +#else public ::boost::type_erasure::detail::compute_bases< ::boost::type_erasure::any, Concept, T >::type +#endif { typedef ::boost::type_erasure::binding table_type; public: /** INTERNAL ONLY */ typedef Concept _boost_type_erasure_concept_type; + +#if defined(BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS) + using _boost_type_erasure_base = ::boost::type_erasure::any_constructor_control< + ::boost::type_erasure::any_constructor_impl< + Concept, + T + > + >; + using _boost_type_erasure_base::_boost_type_erasure_base; +#else + /** INTERNAL ONLY */ any(const ::boost::type_erasure::detail::storage& data_arg, const table_type& table_arg) : table(table_arg), @@ -183,7 +738,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair > + ::boost::mpl::map1< ::boost::mpl::pair > >() )), data(data_arg) @@ -224,7 +779,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, typename ::boost::remove_cv::type>::type), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair::type>::type> > + ::boost::mpl::map1< ::boost::mpl::pair::type>::type> > >() )), data(std::forward(data_arg)) @@ -269,7 +824,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U*), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair > + ::boost::mpl::map1< ::boost::mpl::pair > >() )), data(data_arg) @@ -307,7 +862,7 @@ public: * * \param other The object to make a copy of. * - * \pre @c Concept must contain @ref constructible. + * \pre @c Concept must contain @ref constructible "constructible". * \pre @c Concept must not refer to any non-deduced placeholder besides @c T. * \pre After substituting @c T for @c Tag2, the requirements of * @c Concept2 must be a superset of the requirements of @@ -320,7 +875,7 @@ public: any(const any& other) : table( ::boost::type_erasure::detail::access::table(other), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, typename ::boost::remove_const< @@ -344,7 +899,7 @@ public: * \param binding Specifies the mapping between the placeholders * used by the two concepts. * - * \pre @c Concept must contain @ref constructible. + * \pre @c Concept must contain @ref constructible "constructible". * \pre @c Map must be an MPL map with keys for all the non-deduced * placeholders used by @c Concept and values for the corresponding * placeholders in @c Concept2. @@ -372,7 +927,7 @@ public: * \param other The object to make a copy of. * \param binding Specifies the bindings of placeholders to actual types. * - * \pre @c Concept must contain @ref constructible. + * \pre @c Concept must contain @ref constructible "constructible". * \pre The type stored in @c other must match the type expected by * @c binding. * @@ -467,7 +1022,7 @@ public: any(any& other) : table( ::boost::type_erasure::detail::access::table(other), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, typename ::boost::remove_const< @@ -486,7 +1041,7 @@ public: any(any&& other) : table( ::boost::type_erasure::detail::access::table(other), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, typename ::boost::remove_const< @@ -884,7 +1439,7 @@ public: #endif -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) template const table_type& _boost_type_erasure_extract_table( @@ -926,7 +1481,7 @@ public: ) {} - // disambiguate + // disambiguating overloads template any(binding& binding_arg, U0&& u0, U&&... u) : table(binding_arg), @@ -961,28 +1516,44 @@ public: #endif #endif - - /** - * Assigns to an @ref any. - * - * If an appropriate overload of @ref assignable is not available - * and @ref relaxed is in @c Concept, falls back on - * constructing from @c other. - * - * \throws Whatever the assignment operator of the contained - * type throws. When falling back on construction, - * throws @c std::bad_alloc or whatever the copy - * constructor of the contained type throws. In - * this case assignment provides the strong exception - * guarantee. When calling the assignment operator - * of the contained type, the exception guarantee is - * whatever the contained type provides. - */ + + /** INTERNAL ONLY */ any& operator=(const any& other) { _boost_type_erasure_resolve_assign(other); return *this; } + /** INTERNAL ONLY */ + any& operator=(any& other) + { + _boost_type_erasure_resolve_assign(other); + return *this; + } + +#endif // BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template + any& operator=(U& other) + { + _boost_type_erasure_resolve_assign(other); + return *this; + } + template + any& operator=(const U& other) + { + _boost_type_erasure_resolve_assign(other); + return *this; + } +#else +#ifndef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + /** INTERNAL ONLY */ + any& operator=(any&& other) + { + _boost_type_erasure_resolve_assign(std::move(other)); + return *this; + } +#endif /** * Assigns to an @ref any. * @@ -990,45 +1561,123 @@ public: * and @ref relaxed is in @c Concept, falls back on * constructing from @c other. * + * \note If @c U is an @ref any, then this can decide dynamically + * whether to use construction based on the type stored in other. + * * \throws Whatever the assignment operator of the contained * type throws. When falling back on construction, - * throws @c std::bad_alloc or whatever the copy + * throws @c std::bad_alloc or whatever the move (or copy) * constructor of the contained type throws. In - * this case assignment provides the strong exception - * guarantee. When calling an assignment operator + * this case move assignment provides the strong exception + * guarantee. When calling a (move) assignment operator * of the contained type, the exception guarantee is * whatever the contained type provides. */ template - any& operator=(const U& other) + any& operator=(U&& other) { - _boost_type_erasure_resolve_assign(other); + _boost_type_erasure_resolve_assign(std::forward(other)); return *this; } +#endif + +#ifndef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS /** * \pre @c Concept includes @ref destructible "destructible". */ ~any() { - table.template find >()(data); + ::boost::type_erasure::detail::access::table(*this).template find< + ::boost::type_erasure::destructible + >()(::boost::type_erasure::detail::access::data(*this)); } +#endif -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS /** INTERNAL ONLY */ - operator param() & { return param(data, table); } + operator param() & + { + return param( + boost::type_erasure::detail::access::data(*this), + boost::type_erasure::detail::access::table(*this)); + } /** INTERNAL ONLY */ - operator param() && { return param(data, table); } + operator param() && { + return param( + boost::type_erasure::detail::access::data(*this), + boost::type_erasure::detail::access::table(*this)); + } #endif private: +#ifndef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + /** INTERNAL ONLY */ + void _boost_type_erasure_swap(any& other) + { + ::std::swap(data, other.data); + ::std::swap(table, other.table); + } +#else + void _boost_type_erasure_swap(any& other) + { + ::std::swap(this->_boost_type_erasure_data, other._boost_type_erasure_data); + ::std::swap(this->_boost_type_erasure_table, other._boost_type_erasure_table); + } +#endif +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + /** INTERNAL ONLY */ + template + void _boost_type_erasure_resolve_assign(Other&& other) + { + _boost_type_erasure_assign_impl( + std::forward(other), + false? this->_boost_type_erasure_deduce_assign( + ::boost::type_erasure::detail::make_fallback( + std::forward(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval(). + _boost_type_erasure_deduce_assign(std::forward(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + ::boost::type_erasure::is_relaxed() + ); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + ::boost::mpl::false_) + { + ::boost::type_erasure::call(assignable(), *this, std::forward(other)); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + ::boost::mpl::true_) + { + ::boost::type_erasure::call(assignable(), *this, std::forward(other)); + } /** INTERNAL ONLY */ - void _boost_type_erasure_swap(any& other) + template + void _boost_type_erasure_assign_impl( + Other&& other, + const void*, + ::boost::mpl::true_) { - ::std::swap(data, other.data); - ::std::swap(table, other.table); + any temp(std::forward(other)); + _boost_type_erasure_swap(temp); } +#else /** INTERNAL ONLY */ template - void _boost_type_erasure_resolve_assign(const Other& other) + void _boost_type_erasure_resolve_assign(Other& other) { _boost_type_erasure_assign_impl( other, @@ -1051,7 +1700,7 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable*, ::boost::mpl::false_) { @@ -1060,7 +1709,7 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable*, ::boost::mpl::true_) { @@ -1069,16 +1718,121 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const void*, ::boost::mpl::true_) { any temp(other); _boost_type_erasure_swap(temp); } +#endif /** INTERNAL ONLY */ template void _boost_type_erasure_resolve_assign(const any& other) + { + _boost_type_erasure_resolve_assign_any(other); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_resolve_assign(any& other) + { + _boost_type_erasure_resolve_assign_any(other); + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + /** INTERNAL ONLY */ + template + void _boost_type_erasure_resolve_assign(any&& other) + { + _boost_type_erasure_resolve_assign_any(std::move(other)); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_resolve_assign_any(Other&& other) + { + _boost_type_erasure_assign_impl( + std::forward(other), + false? this->_boost_type_erasure_deduce_assign( + ::boost::type_erasure::detail::make_fallback( + std::forward(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval(). + _boost_type_erasure_deduce_assign(std::forward(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + false? this->_boost_type_erasure_deduce_constructor( + ::boost::type_erasure::detail::make_fallback( + std::forward(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval(). + _boost_type_erasure_deduce_constructor(std::forward(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + ::boost::type_erasure::is_relaxed() + ); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + const void*, + ::boost::mpl::false_) + { + ::boost::type_erasure::call(assignable(), *this, std::forward(other)); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + const void*, + ::boost::mpl::true_) + { + ::boost::type_erasure::call(assignable(), *this, std::forward(other)); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const void*, + const constructible*, + ::boost::mpl::true_) + { + any temp(std::forward(other)); + _boost_type_erasure_swap(temp); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + const constructible*, + ::boost::mpl::true_) + { + if(::boost::type_erasure::check_match(assignable(), *this, other)) // const reference to other is enough! + { + ::boost::type_erasure::unchecked_call(assignable(), *this, std::forward(other)); + } + else + { + any temp(std::forward(other)); + _boost_type_erasure_swap(temp); + } + } +#else + /** INTERNAL ONLY */ + template + void _boost_type_erasure_resolve_assign_any(Other& other) { _boost_type_erasure_assign_impl( other, @@ -1114,7 +1868,7 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable*, const void*, ::boost::mpl::false_) @@ -1124,7 +1878,7 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable*, const void*, ::boost::mpl::true_) @@ -1134,7 +1888,7 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const void*, const constructible*, ::boost::mpl::true_) @@ -1145,7 +1899,7 @@ private: /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable*, const constructible*, ::boost::mpl::true_) @@ -1160,11 +1914,17 @@ private: _boost_type_erasure_swap(temp); } } +#endif friend struct ::boost::type_erasure::detail::access; +#ifndef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS // The table has to be initialized first for exception // safety in some constructors. table_type table; ::boost::type_erasure::detail::storage data; +#else + template + friend struct ::boost::type_erasure::any_constructor_impl; +#endif }; template @@ -1209,7 +1969,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair > + ::boost::mpl::map1< ::boost::mpl::pair > >() )) { @@ -1293,7 +2053,7 @@ public: : data(::boost::type_erasure::detail::access::data(other)), table( ::boost::type_erasure::detail::access::table(other), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, Tag2 @@ -1326,7 +2086,7 @@ public: : data(::boost::type_erasure::detail::access::data(other)), table( ::boost::type_erasure::detail::access::table(other), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, typename ::boost::remove_reference::type @@ -1432,26 +2192,27 @@ public: table(binding_arg) {} - /** - * Assigns to an @ref any. - * - * If an appropriate overload of @ref assignable is not available - * and @ref relaxed is in @c Concept, falls back on - * constructing from @c other. - * - * \throws Whatever the assignment operator of the contained - * type throws. When falling back on construction, - * throws @c std::bad_alloc. In this case assignment - * provides the strong exception guarantee. When - * calling the assignment operator of the contained type, - * the exception guarantee is whatever the contained type provides. - */ + /** INTERNAL ONLY */ any& operator=(const any& other) { _boost_type_erasure_resolve_assign(other); return *this; } + /** INTERNAL ONLY */ + any& operator=(any& other) + { + _boost_type_erasure_resolve_assign(other); + return *this; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + /** INTERNAL ONLY */ + any& operator=(any&& other) + { + _boost_type_erasure_resolve_assign(std::move(other)); + return *this; + } /** * Assigns to an @ref any. * @@ -1461,40 +2222,35 @@ public: * * \throws Whatever the assignment operator of the contained * type throws. When falling back on construction, - * throws @c std::bad_alloc. In this case assignment + * can only throw @c std::bad_alloc if @c U is an @ref any + * that uses a different @c Concept. In this case assignment * provides the strong exception guarantee. When * calling the assignment operator of the contained type, * the exception guarantee is whatever the contained type provides. */ template + any& operator=(U&& other) + { + _boost_type_erasure_resolve_assign(std::forward(other)); + return *this; + } +#else + template any& operator=(U& other) { _boost_type_erasure_resolve_assign(other); return *this; } - /** - * Assigns to an @ref any. - * - * If an appropriate overload of @ref assignable is not available - * and @ref relaxed is in @c Concept, falls back on - * constructing from @c other. - * - * \throws Whatever the assignment operator of the contained - * type throws. When falling back on construction, - * throws @c std::bad_alloc. In this case assignment - * provides the strong exception guarantee. When - * calling the assignment operator of the contained type, - * the exception guarantee is whatever the contained type provides. - */ template any& operator=(const U& other) { _boost_type_erasure_resolve_assign(other); return *this; } +#endif -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS /** INTERNAL ONLY */ operator param() const { return param(data, table); } #endif @@ -1506,6 +2262,71 @@ private: ::std::swap(data, other.data); ::std::swap(table, other.table); } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + /** INTERNAL ONLY */ + template + void _boost_type_erasure_resolve_assign(Other&& other) + { + _boost_type_erasure_assign_impl( + std::forward(other), + false? this->_boost_type_erasure_deduce_assign( + ::boost::type_erasure::detail::make_fallback( + std::forward(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval(). + _boost_type_erasure_deduce_assign(std::forward(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + ::boost::mpl::and_< + ::boost::type_erasure::is_relaxed, + ::boost::is_convertible +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900)) + , ::boost::mpl::not_< + ::boost::type_erasure::detail::is_rvalue_for_any + > +#endif + >() + ); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + ::boost::mpl::false_) + { + ::boost::type_erasure::call(assignable(), *this, std::forward(other)); + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable*, + ::boost::mpl::true_) + { + if(::boost::type_erasure::check_match(assignable(), *this, other)) { + ::boost::type_erasure::unchecked_call(assignable(), *this, std::forward(other)); + } else { + any temp(std::forward(other)); + _boost_type_erasure_swap(temp); + } + } + /** INTERNAL ONLY */ + template + void _boost_type_erasure_assign_impl( + Other&& other, + const void*, + ::boost::mpl::true_) + { + any temp(std::forward(other)); + _boost_type_erasure_swap(temp); + } +#else /** INTERNAL ONLY */ template void _boost_type_erasure_resolve_assign(Other& other) @@ -1525,7 +2346,10 @@ private: >() ) ) : 0, - ::boost::type_erasure::is_relaxed() + ::boost::mpl::and_< + ::boost::type_erasure::is_relaxed, + ::boost::is_convertible + >() ); } /** INTERNAL ONLY */ @@ -1561,6 +2385,7 @@ private: any temp(other); _boost_type_erasure_swap(temp); } +#endif friend struct ::boost::type_erasure::detail::access; ::boost::type_erasure::detail::storage data; @@ -1604,7 +2429,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair > + ::boost::mpl::map1< ::boost::mpl::pair > >() )) { @@ -1701,7 +2526,7 @@ public: : data(::boost::type_erasure::detail::access::data(other)), table( ::boost::type_erasure::detail::access::table(other), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, typename ::boost::remove_const< @@ -1780,7 +2605,7 @@ public: return *this; } -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS /** INTERNAL ONLY */ operator param() const { return param(data, table); } #endif @@ -1841,7 +2666,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair > + ::boost::mpl::map1< ::boost::mpl::pair > >() )) { @@ -1926,7 +2751,7 @@ public: : data(::boost::type_erasure::detail::access::data(other)), table( std::move(::boost::type_erasure::detail::access::table(other)), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, Tag2 @@ -1959,7 +2784,7 @@ public: : data(::boost::type_erasure::detail::access::data(other)), table( std::move(::boost::type_erasure::detail::access::table(other)), - ::boost::mpl::map< + ::boost::mpl::map1< ::boost::mpl::pair< T, typename ::boost::remove_reference::type @@ -2065,20 +2890,7 @@ public: table(binding_arg) {} - /** - * Assigns to an @ref any. - * - * If an appropriate overload of @ref assignable is not available - * and @ref relaxed is in @c Concept, falls back on - * constructing from @c other. - * - * \throws Whatever the assignment operator of the contained - * type throws. When falling back on construction, - * throws @c std::bad_alloc. In this case assignment - * provides the strong exception guarantee. When - * calling the assignment operator of the contained type, - * the exception guarantee is whatever the contained type provides. - */ + /** INTERNAL ONLY */ any& operator=(const any& other) { _boost_type_erasure_resolve_assign(other); @@ -2094,40 +2906,20 @@ public: * * \throws Whatever the assignment operator of the contained * type throws. When falling back on construction, - * throws @c std::bad_alloc. In this case assignment - * provides the strong exception guarantee. When - * calling the assignment operator of the contained type, - * the exception guarantee is whatever the contained type provides. - */ - template - any& operator=(U& other) - { - _boost_type_erasure_resolve_assign(other); - return *this; - } - - /** - * Assigns to an @ref any. - * - * If an appropriate overload of @ref assignable is not available - * and @ref relaxed is in @c Concept, falls back on - * constructing from @c other. - * - * \throws Whatever the assignment operator of the contained - * type throws. When falling back on construction, - * throws @c std::bad_alloc. In this case assignment + * can only throw @c std::bad_alloc if @c U is an @ref any + * that uses a different @c Concept. In this case assignment * provides the strong exception guarantee. When * calling the assignment operator of the contained type, * the exception guarantee is whatever the contained type provides. */ template - any& operator=(const U& other) + any& operator=(U&& other) { - _boost_type_erasure_resolve_assign(other); + _boost_type_erasure_resolve_assign(std::forward(other)); return *this; } -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS /** INTERNAL ONLY */ operator param() const { return param(data, table); } #endif @@ -2141,57 +2933,68 @@ private: } /** INTERNAL ONLY */ template - void _boost_type_erasure_resolve_assign(Other& other) + void _boost_type_erasure_resolve_assign(Other&& other) { _boost_type_erasure_assign_impl( - other, + std::forward(other), false? this->_boost_type_erasure_deduce_assign( ::boost::type_erasure::detail::make_fallback( - other, + std::forward(other), ::boost::mpl::bool_< - sizeof( - ::boost::type_erasure::detail::check_overload( - ::boost::declval(). - _boost_type_erasure_deduce_assign(other) - ) + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval(). + _boost_type_erasure_deduce_assign(std::forward(other)) + ) ) == sizeof(::boost::type_erasure::detail::yes) >() ) ) : 0, - ::boost::type_erasure::is_relaxed() + ::boost::mpl::and_< + ::boost::type_erasure::is_relaxed, + ::boost::is_convertible + >() ); } /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - Other& other, + Other&& other, const assignable*, ::boost::mpl::false_) { - ::boost::type_erasure::call(assignable(), *this, other); + ::boost::type_erasure::call( + assignable(), + // lose rvalueness of this + ::boost::type_erasure::param(data, table), + std::forward(other)); } /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - Other& other, + Other&& other, const assignable*, ::boost::mpl::true_) { if(::boost::type_erasure::check_match(assignable(), *this, other)) { - ::boost::type_erasure::unchecked_call(assignable(), *this, other); + ::boost::type_erasure::unchecked_call( + assignable(), + // lose rvalueness of this + ::boost::type_erasure::param(data, table), + std::forward(other)); } else { - any temp(other); + any temp(std::forward(other)); _boost_type_erasure_swap(temp); } } /** INTERNAL ONLY */ template void _boost_type_erasure_assign_impl( - Other& other, + Other&& other, const void*, ::boost::mpl::true_) { - any temp(other); + any temp(std::forward(other)); _boost_type_erasure_swap(temp); } @@ -2202,6 +3005,17 @@ private: #endif +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES +template +using any_ref = any; +template +using any_cref = any; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template +using any_rvref = any; +#endif +#endif + } } diff --git a/boost/type_erasure/any_cast.hpp b/boost/type_erasure/any_cast.hpp index ea8d66a9a9..939535c470 100644 --- a/boost/type_erasure/any_cast.hpp +++ b/boost/type_erasure/any_cast.hpp @@ -109,7 +109,7 @@ bool check_any_cast(const any& arg) * \endcode * * \pre if @c arg is a pointer, @c T must be a pointer type. - * \pre @c Concept must contain @ref typeid_<Tag>. + * \pre @c Concept must contain @ref typeid_ "typeid_". * * \throws bad_any_cast if @c arg doesn't contain * an object of type @c T and we're casting diff --git a/boost/type_erasure/builtin.hpp b/boost/type_erasure/builtin.hpp index 812b34face..7af5d84b23 100644 --- a/boost/type_erasure/builtin.hpp +++ b/boost/type_erasure/builtin.hpp @@ -12,10 +12,15 @@ #define BOOST_TYPE_ERASURE_BUILTIN_HPP_INCLUDED #include +#include +#include #include #include #include #include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +# include // std::move +#endif #include namespace boost { @@ -64,27 +69,60 @@ struct copy_constructible : ::boost::mpl::vector, destructible > {}; +#ifdef BOOST_TYPE_ERASURE_DOXYGEN + /** * Enables assignment of @ref any types. */ -template +template struct assignable { - static void apply(T& dst, const U& src) { dst = src; } + static void apply(T& dst, U src); +}; + +#else + +/** + * Enables assignment of @ref any types. + */ +template +struct assignable : + ::boost::mpl::vector > +{}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +/** INTERNAL ONLY */ +template +struct assignable +{ + static void apply(T& dst, U&& src) { dst = std::forward(src); } +}; + +#endif + +/** INTERNAL ONLY */ +template +struct assignable +{ + static void apply(T& dst, U& src) { dst = src; } }; /** INTERNAL ONLY */ template -struct concept_interface, Base, T> : Base +struct concept_interface, Base, T, + typename ::boost::enable_if_c< ::boost::is_reference::value>::type> : Base { using Base::_boost_type_erasure_deduce_assign; assignable* _boost_type_erasure_deduce_assign( - typename ::boost::type_erasure::rebind_any::type) + typename ::boost::type_erasure::as_param::type) { return 0; } }; +#endif + /** * Enables runtime type information. This is required * if you want to use \any_cast or \typeid_of. diff --git a/boost/type_erasure/call.hpp b/boost/type_erasure/call.hpp index 2a8ee2c580..8234862cae 100644 --- a/boost/type_erasure/call.hpp +++ b/boost/type_erasure/call.hpp @@ -42,12 +42,16 @@ namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN + template class any; template class binding; +#endif + namespace detail { template @@ -293,6 +297,8 @@ namespace detail { template void ignore(const T&...) {} +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + template const ::boost::type_erasure::binding< typename ::boost::type_erasure::detail::extract_concept::type>* @@ -312,6 +318,29 @@ extract_table(R(*)(T...), const U&... arg) return result; } +#else + +template +const ::boost::type_erasure::binding< + ::boost::type_erasure::detail::extract_concept_t< ::boost::mp11::mp_list, ::boost::mp11::mp_list > >* +extract_table(R(*)(T...), const U&... arg) +{ + const ::boost::type_erasure::binding< + ::boost::type_erasure::detail::extract_concept_t< + ::boost::mp11::mp_list, ::boost::mp11::mp_list > >* result = 0; + + // the order that we run maybe_get_table in doesn't matter + ignore(::boost::type_erasure::detail::maybe_get_table( + arg, + result, + ::boost::type_erasure::detail::is_placeholder_arg())...); + + BOOST_ASSERT(result != 0); + return result; +} + +#endif + template struct call_impl_dispatch; @@ -354,6 +383,8 @@ struct call_impl : { }; +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + template struct call_impl : ::boost::type_erasure::detail::call_impl_dispatch< @@ -368,6 +399,24 @@ struct call_impl : { }; +#else + +template +struct call_impl : + ::boost::type_erasure::detail::call_impl_dispatch< + R(T...), + void(U...), + ::boost::type_erasure::detail::extract_concept_t< + ::boost::mp11::mp_list, + ::boost::mp11::mp_list< ::boost::remove_reference_t...> + >, + ::boost::type_erasure::detail::is_placeholder_arg::value + > +{ +}; + +#endif + } template< diff --git a/boost/type_erasure/check_match.hpp b/boost/type_erasure/check_match.hpp index d4c68f51bf..6f76edd4a5 100644 --- a/boost/type_erasure/check_match.hpp +++ b/boost/type_erasure/check_match.hpp @@ -33,12 +33,16 @@ namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN + template struct typeid_; template class binding; +#endif + namespace detail { template @@ -94,8 +98,8 @@ bool check_match(const Op& f, U&&... args); namespace detail { -template -bool check_table(const ::boost::type_erasure::binding* t, void(*)()) +template +bool check_table(const ::boost::type_erasure::binding* /*t*/, R(*)()) { return true; } @@ -134,6 +138,8 @@ bool check_match( arg...); } +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + template< class Op, class... U @@ -152,6 +158,42 @@ bool check_match( #else +namespace detail { + +template +struct get_args; + +template +struct get_args { typedef ::boost::mp11::mp_list type; }; + +template +using get_args_t = typename get_args::type; + +} + +template< + class Op, + class... U +> +bool check_match( + const Op&, + U&&... arg) +{ + const ::boost::type_erasure::binding< + ::boost::type_erasure::detail::extract_concept_t< + ::boost::type_erasure::detail::get_args_t< + typename ::boost::type_erasure::detail::get_signature::type + >, + ::boost::mp11::mp_list< ::boost::remove_reference_t...> > >* p = 0; + + return ::boost::type_erasure::detail::check_table( + p, static_cast::type*>(0), arg...); +} + +#endif + +#else + #define BOOST_PP_FILENAME_1 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) #include BOOST_PP_ITERATE() diff --git a/boost/type_erasure/concept_of.hpp b/boost/type_erasure/concept_of.hpp index 43b4de52d7..f4b12dc743 100644 --- a/boost/type_erasure/concept_of.hpp +++ b/boost/type_erasure/concept_of.hpp @@ -11,15 +11,21 @@ #ifndef BOOST_TYPE_ERASURE_CONCEPT_OF_HPP_INCLUDED #define BOOST_TYPE_ERASURE_CONCEPT_OF_HPP_INCLUDED +#include + namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN + template class any; template class param; +#endif + /** * A metafunction returning the concept corresponding * to an @ref any. It will also work for all bases @@ -52,6 +58,13 @@ struct concept_of< ::boost::type_erasure::param > typedef Concept type; }; +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES + +template +using concept_of_t = typename ::boost::type_erasure::concept_of::type; + +#endif + } } diff --git a/boost/type_erasure/constructible.hpp b/boost/type_erasure/constructible.hpp index 5f1a413058..dd3c0f0004 100644 --- a/boost/type_erasure/constructible.hpp +++ b/boost/type_erasure/constructible.hpp @@ -41,7 +41,7 @@ struct get_null_vtable_entry; template struct vtable_adapter; -}; +} #ifdef BOOST_TYPE_ERASURE_DOXYGEN @@ -88,7 +88,7 @@ struct concept_interface< using Base::_boost_type_erasure_deduce_constructor; ::boost::type_erasure::constructible* _boost_type_erasure_deduce_constructor( - typename ::boost::type_erasure::as_param::type...) + typename ::boost::type_erasure::as_param::type...) const { return 0; } @@ -168,7 +168,7 @@ struct concept_interface< using Base::_boost_type_erasure_deduce_constructor; ::boost::type_erasure::constructible* _boost_type_erasure_deduce_constructor( - BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_ARG_DECL, ~)) + BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_ARG_DECL, ~)) const { return 0; } diff --git a/boost/type_erasure/deduced.hpp b/boost/type_erasure/deduced.hpp index b9ed96094c..966c29bfc0 100644 --- a/boost/type_erasure/deduced.hpp +++ b/boost/type_erasure/deduced.hpp @@ -37,7 +37,11 @@ struct deduced : ::boost::type_erasure::placeholder ::boost::mpl::empty< typename ::boost::type_erasure::detail::get_placeholders< Metafunction, +#ifndef BOOST_TYPE_ERASURE_USE_MP11 ::boost::mpl::set0<> +#else + ::boost::mp11::mp_list<> +#endif >::type >, Metafunction, diff --git a/boost/type_erasure/derived.hpp b/boost/type_erasure/derived.hpp index 42316d2b57..844d9c2072 100644 --- a/boost/type_erasure/derived.hpp +++ b/boost/type_erasure/derived.hpp @@ -31,6 +31,13 @@ struct derived #endif }; +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES + +template +using derived_t = typename T::_boost_type_erasure_derived_type; + +#endif + } } 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 #include +#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 +#include +#endif + namespace boost { namespace type_erasure { @@ -23,6 +35,9 @@ class any; template class param; +template +class binding; + namespace detail { struct access @@ -34,11 +49,51 @@ struct access return static_cast(arg).table; } template - static const typename any::table_type& + static const ::boost::type_erasure::binding& table(const ::boost::type_erasure::param& arg) + { + return table(arg._impl); + } + template + static const ::boost::type_erasure::binding& + table(const ::boost::type_erasure::param& arg) + { + return arg._impl.table; + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + static const ::boost::type_erasure::binding& + table(const ::boost::type_erasure::param& arg) { return arg._impl.table; } +#endif +#ifdef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + template::value>::type> + static const typename any::table_type& + table(const ::boost::type_erasure::any_base< ::boost::type_erasure::any >& arg) + { + return static_cast&>(arg)._boost_type_erasure_table; + } + template + static ::boost::type_erasure::detail::storage& + data(::boost::type_erasure::any_base< ::boost::type_erasure::any >& arg) + { + return static_cast< ::boost::type_erasure::any&>(arg)._boost_type_erasure_data; + } + template + static const ::boost::type_erasure::detail::storage& + data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any >& arg) + { + return static_cast&>(arg)._boost_type_erasure_data; + } + template + static ::boost::type_erasure::detail::storage&& + data(::boost::type_erasure::any_base< ::boost::type_erasure::any >&& arg) + { + return std::move(static_cast< ::boost::type_erasure::any&&>(arg)._boost_type_erasure_data); + } +#endif template static ::boost::type_erasure::detail::storage& data(::boost::type_erasure::any_base& arg) @@ -59,6 +114,12 @@ struct access } template static ::boost::type_erasure::detail::storage& + data(::boost::type_erasure::any_base< ::boost::type_erasure::any >& arg) + { + return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< ::boost::type_erasure::any&>(arg).data); + } + template + static ::boost::type_erasure::detail::storage& data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any >& arg) { return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any&>(arg).data); @@ -72,6 +133,12 @@ struct access template static ::boost::type_erasure::detail::storage& data(::boost::type_erasure::param& arg) + { + return data(arg._impl); + } + template + static ::boost::type_erasure::detail::storage& + data(::boost::type_erasure::param& arg) { return arg._impl.data; } @@ -84,6 +151,12 @@ struct access template static const ::boost::type_erasure::detail::storage& data(const ::boost::type_erasure::param& arg) + { + return data(arg._impl); + } + template + static const ::boost::type_erasure::detail::storage& + data(const ::boost::type_erasure::param& arg) { return arg._impl.data; } @@ -104,18 +177,48 @@ struct access } template static ::boost::type_erasure::detail::storage&& + data(::boost::type_erasure::any_base< ::boost::type_erasure::any >&& arg) + { + return std::move(static_cast< ::boost::type_erasure::any&>(arg).data); + } + template + static ::boost::type_erasure::detail::storage&& data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any >& arg) { return std::move(const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any&>(arg).data)); } + template + static ::boost::type_erasure::detail::storage& + data(::boost::type_erasure::any_base< ::boost::type_erasure::any >&& arg) + { + return std::move(static_cast< ::boost::type_erasure::any&>(arg).data); + } template static ::boost::type_erasure::detail::storage&& data(::boost::type_erasure::param&& arg) + { + return std::move(data(arg._impl)); + } + template + static ::boost::type_erasure::detail::storage&& + data(::boost::type_erasure::param&& arg) { return std::move(arg._impl.data); } template + static ::boost::type_erasure::detail::storage& + data(::boost::type_erasure::param&& arg) + { + return arg._impl.data; + } + template + static const ::boost::type_erasure::detail::storage& + data(::boost::type_erasure::param&& arg) + { + return arg._impl.data; + } + template static ::boost::type_erasure::detail::storage&& data(::boost::type_erasure::param& 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 struct get_placeholders; -template -struct rebind_placeholders; - -template -struct rebind_placeholders_in_argument; - template struct vtable_adapter; -template -struct rebind_placeholders, Bindings> -{ - typedef vtable_adapter< - typename rebind_placeholders::type, - typename rebind_placeholders_in_argument::type - > type; -}; - template struct get_placeholders, Out> { @@ -308,11 +293,13 @@ struct vtable_adapter 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 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 +using check_placeholder_arg_t = + typename ::boost::type_erasure::detail::check_placeholder_arg_impl< + P, + typename ::boost::type_erasure::detail::qualified_placeholder::type + >::type; + +template +using check_nonplaceholder_arg_t = typename ::boost::is_convertible::type; + +template +using check_arg_t = + ::boost::type_erasure::detail::eval_if< + ::boost::type_erasure::is_placeholder< + ::boost::remove_cv_t< + ::boost::remove_reference_t + > + >::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 +struct check_arg +{ + typedef ::boost::type_erasure::detail::check_arg_t type; +}; + +template +struct check_call { + typedef ::boost::mp11::mp_all< + typename ::boost::type_erasure::detail::check_arg::type... + > type; +}; + +#else + template struct check_arg { @@ -135,10 +178,37 @@ struct check_arg >::type type; }; +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #define BOOST_PP_FILENAME_1 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) #include BOOST_PP_ITERATE() +#else + +template +struct and_; + +template +struct and_ : boost::mpl::eval_if_c, boost::mpl::false_>::type {}; + +template +struct and_ : T1::type {}; + +template<> +struct and_<> : boost::mpl::true_ {}; + +template +struct check_call { + typedef typename ::boost::type_erasure::detail::and_< + ::boost::type_erasure::detail::check_arg... + >::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 > : boost::mpl::true_ {}; // returns true if Map has a key for every non-deduced placeholder in Concept template struct check_map { +#ifndef BOOST_TYPE_ERASURE_USE_MP11 typedef typename normalize_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::type >::type type; + +#else + typedef ::boost::type_erasure::detail::get_all_placeholders< + ::boost::type_erasure::detail::normalize_concept_t + > 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 + >, + ::boost::mp11::mp_transform< + ::boost::mp11::mp_second, + ::boost::type_erasure::detail::make_mp_list + > + > + > okay_placeholders; + template + using check_placeholder = ::boost::mpl::or_< + ::boost::type_erasure::detail::is_deduced

, + ::boost::mp11::mp_set_contains + >; + typedef ::boost::mp11::mp_all_of type; +#endif }; template 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 -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 +struct dynamic_binding_element { + typedef const std::type_info * type; }; template @@ -50,12 +56,15 @@ struct append_to_key { template struct dynamic_vtable : dynamic_binding_impl

... { dynamic_vtable() = default; - template - constexpr dynamic_vtable(T* ...t) : dynamic_binding_impl

{t}... {} + constexpr dynamic_vtable(typename dynamic_binding_element

::type ...t) : dynamic_binding_impl

(t)... {} template typename F::type lookup(F*) const { key_type key; +#ifndef BOOST_TYPE_ERASURE_USE_MP11 typedef typename ::boost::type_erasure::detail::get_placeholders >::type placeholders; +#else + typedef typename ::boost::type_erasure::detail::get_placeholders >::type placeholders; +#endif typedef typename ::boost::mpl::fold< placeholders, ::boost::mpl::map0<>, @@ -71,8 +80,13 @@ struct dynamic_vtable : dynamic_binding_impl

... { } template void convert_from(const Src& src) { +#ifndef BOOST_TYPE_ERASURE_USE_MP11 *this = dynamic_vtable( (&src.lookup((::boost::type_erasure::typeid_::type>*)0)())...); +#else + *this = dynamic_vtable( + (&src.lookup((::boost::type_erasure::typeid_< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find > >*)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 { typedef T type; }; template<> struct combine_concepts { typedef void type; }; +#ifdef BOOST_TYPE_ERASURE_USE_MP11 + +template +using combine_concepts_t = typename ::boost::type_erasure::detail::combine_concepts::type; + +template +using extract_concept_or_void = + ::boost::mp11::mp_eval_if_c< + !::boost::type_erasure::is_placeholder< + ::boost::remove_cv_t< + ::boost::remove_reference_t + > + >::value, + void, + ::boost::type_erasure::concept_of_t, U + >; + +template +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 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 struct extract_concept; @@ -82,7 +109,6 @@ struct extract_concept }; #else -//#endif #define BOOST_PP_FILENAME_1 #define BOOST_PP_ITERATION_LIMITS (1, BOOST_TYPE_ERASURE_MAX_ARITY) @@ -90,6 +116,8 @@ struct extract_concept #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 #include #include +#include #include #include @@ -28,6 +29,87 @@ namespace boost { namespace type_erasure { namespace detail { +#ifdef BOOST_TYPE_ERASURE_USE_MP11 + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = ::boost::type_erasure::detail::eval_if< + ::boost::type_erasure::is_placeholder::value, + ::boost::mp11::mp_set_push_back, + ::boost::type_erasure::detail::first, + Out, T + >; +}; + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl::template apply; +}; + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl::template apply; +}; + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl::template apply; +}; + +template +using get_placeholders_f = typename get_placeholders_in_argument_impl::template apply; + +template +using get_placeholders_impl = + ::boost::mp11::mp_fold< + ::boost::mp11::mp_list, + Out, + ::boost::type_erasure::detail::get_placeholders_f + >; + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = ::boost::type_erasure::detail::get_placeholders_impl; +}; + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = ::boost::type_erasure::detail::get_placeholders_impl; +}; + +template +struct get_placeholders_in_argument_impl +{ + template + using apply = ::boost::type_erasure::detail::get_placeholders_impl; +}; + +template +struct get_placeholders; + +template class F, class... T, class Out> +struct get_placeholders, Out> +{ + using type = ::boost::type_erasure::detail::get_placeholders_impl; +}; + +template +using get_placeholders_t = typename ::boost::type_erasure::detail::get_placeholders::type; + +#else + template struct get_placeholders_in_argument { @@ -88,11 +170,19 @@ struct get_placeholders, Out> template struct get_placeholders_in_argument { - typedef typename ::boost::type_erasure::detail::get_placeholders_in_argument< - R, - Out - >::type type0; - typedef typename get_placeholders_impl::type type; + typedef typename get_placeholders_impl::type type; +}; + +template +struct get_placeholders_in_argument +{ + typedef typename get_placeholders_impl::type type; +}; + +template +struct get_placeholders_in_argument +{ + typedef typename get_placeholders_impl::type type; }; #else @@ -103,6 +193,8 @@ struct get_placeholders_in_argument #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 +struct make_instantiate_concept_impl; + +template +struct instantiate_concept; + +template +using instantiate_concept_impl = instantiate_concept; + +template +struct make_instantiate_concept_impl< ::boost::mp11::mp_list > +{ + template class F> + using apply = void(F...); +}; + +template +struct instantiate_concept_rebind_f +{ + template + using apply = + typename ::boost::type_erasure::detail::rebind_placeholders< + T, + Map + >::type; +}; + +template +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, + typename ::boost::type_erasure::detail::get_placeholder_normalization_map< + Concept + >::type + >::type + >::template apply, + ::boost::type_erasure::detail::normalize_concept_t + > + >; + +#define BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map) \ + ((void)(typename ::boost::type_erasure::detail::make_instantiate_concept \ + ::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 > > \ + ::template apply< ::boost::type_erasure::detail::instantiate_concept_impl>*)0) + +#else + template 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 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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace type_erasure { +namespace detail { + +template class interface, class Sig, class Concept, class Base, class ID> +using choose_member_interface = typename ::boost::mpl::if_c< ::boost::is_reference

::value, + typename ::boost::mpl::if_c< ::boost::type_erasure::detail::is_non_const_ref

::value, + interface, + Base + >::type, + interface +>::type; + + +struct dummy {}; + +template +struct choose_member_impl; + +template +struct choose_member_impl +{ + template class M, template class S> + using apply = ::boost::mpl::vector1 >; +}; + +template +struct choose_member_impl +{ + template class M, template class S> + using apply = M; +}; + +template class M, template class Self> +using choose_member_impl_t = + typename ::boost::type_erasure::detail::choose_member_impl< + Sig (::boost::type_erasure::detail::dummy::*) + >::template apply; + +template +struct member_interface_chooser +{ + template class C, template class M> + using apply = Base; +}; + +template +struct member_interface_chooser +{ + template class C, template class M> + using apply = ::boost::type_erasure::detail::choose_member_interface< + ::boost::type_erasure::placeholder_of_t, + M, + R(A...), C, Base, T>; +}; + +template +struct member_interface_chooser +{ + template class C, template class M> + using apply = M, Base, const T>; +}; + +template class C, template class M> +struct member_choose_interface +{ + template + using apply = typename ::boost::type_erasure::detail::member_interface_chooser::template apply; +}; + +} +} +} + +#define BOOST_TYPE_ERASURE_MEMBER_I(concept_name, function_name) \ +template \ +struct concept_name; \ + \ +namespace boost_type_erasure_impl { \ + \ +template \ +using concept_name ## self = concept_name; \ + \ +template\ +struct concept_name ## _member_interface; \ + \ +template \ +struct concept_name ## _member_interface : Base\ +{ \ + typedef void _boost_type_erasure_has_member ## function_name; \ + ::boost::type_erasure::rebind_any_t function_name(::boost::type_erasure::as_param_t... a)\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward(a)...); }\ +}; \ + \ +template \ +struct concept_name ## _member_interface : Base \ +{ \ + using Base::function_name; \ + ::boost::type_erasure::rebind_any_t function_name(::boost::type_erasure::as_param_t... a)\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward(a)...); }\ +}; \ + \ +template \ +struct concept_name ## _member_interface : Base\ +{ \ + typedef void _boost_type_erasure_has_member ## function_name; \ + ::boost::type_erasure::rebind_any_t function_name(::boost::type_erasure::as_param_t... a) const\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward(a)...); }\ +}; \ + \ +template \ +struct concept_name ## _member_interface : Base \ +{ \ + using Base::function_name; \ + ::boost::type_erasure::rebind_any_t function_name(::boost::type_erasure::as_param_t... a) const\ + { return ::boost::type_erasure::call(Concept(), *this, std::forward(a)...); }\ +}; \ + \ +template \ +struct concept_name ## member; \ + \ +template \ +struct concept_name ## member { \ + static R apply(T0 t0, T... t) \ + { return t0.function_name(std::forward(t)...); } \ +}; \ + \ +template \ +struct concept_name ## member { \ + static void apply(T0 t0, T... t) \ + { t0.function_name(std::forward(t)...); } \ +}; \ + \ +} \ + \ +template \ +struct concept_name : \ + ::boost::type_erasure::detail::choose_member_impl_t \ +{}; \ + \ +template \ +::boost::type_erasure::detail::member_choose_interface \ +boost_type_erasure_find_interface(concept_name); + +#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 + + +#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 +#include +#include +#include +#include +#include + +namespace boost { +namespace type_erasure { +namespace detail { + +struct mp11_list_inserter +{ + template + using apply = ::boost::mpl::identity< ::boost::mp11::mp_push_back >; +}; + +template +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 +struct make_mp_list_impl< ::boost::mp11::mp_list > +{ + typedef ::boost::mp11::mp_list type; +}; + +template +using make_mp_list = typename make_mp_list_impl::type; + +template +struct eval_if_impl; + +template<> +struct eval_if_impl +{ + template class T, template class F, class... A> + using apply = T; +}; + +template<> +struct eval_if_impl +{ + template class T, template class F, class... A> + using apply = F; +}; + +template class T, template class F, class... A> +using eval_if = typename ::boost::type_erasure::detail::eval_if_impl::template apply; + +template +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 #include #include +#include #include #include @@ -43,7 +44,6 @@ template 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 -struct resolve_same_type -{ - typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, - ::boost::type_erasure::detail::resolve_same_type< - M, - typename ::boost::mpl::at::type - >, - ::boost::mpl::identity - >::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 +struct resolve_same_type +{ + typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key, + ::boost::type_erasure::detail::resolve_same_type< + M, + typename ::boost::mpl::at::type + >, + ::boost::mpl::identity + >::type type; +}; + // M is a map of placeholder substitutions template struct normalize_placeholder @@ -377,20 +379,422 @@ struct collect_concepts Concept, ::boost::type_erasure::detail::substitution_map >::type transformed; + typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence, + ::boost::mpl::fold >, + ::boost::mpl::identity + >::type type1; typedef typename ::boost::mpl::eval_if< ::boost::is_same, - ::boost::mpl::identity, + ::boost::mpl::identity, ::boost::mpl::insert< - Out, + type1, transformed > - >::type type1; - typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence, - ::boost::mpl::fold >, - ::boost::mpl::identity >::type type; }; +#else + +template +struct resolve_same_type_impl; + +template +using resolve_same_type_t = + typename ::boost::type_erasure::detail::resolve_same_type_impl< + (::boost::mp11::mp_map_contains::value) + >::template apply; + +template<> +struct resolve_same_type_impl +{ + template + using apply = ::boost::type_erasure::detail::resolve_same_type_t< + M, + ::boost::mp11::mp_second< ::boost::mp11::mp_map_find > + >; +}; + +template<> +struct resolve_same_type_impl +{ + template + using apply = T; +}; + +// given a partial substitution map from same_type, +// resolves a placeholder as far as possible. +template +using resolve_same_type = ::boost::mpl::identity< ::boost::type_erasure::detail::resolve_same_type_t >; + + +// M is a map of placeholder substitutions + +template +struct normalize_placeholder_impl; + +template +using normalize_placeholder_t = + typename ::boost::type_erasure::detail::normalize_placeholder_impl< + ::boost::mp11::mp_map_contains::value + >::template apply; + +template<> +struct normalize_placeholder_impl +{ + template + using apply = ::boost::type_erasure::detail::normalize_placeholder_t< + M, + typename ::boost::mp11::mp_second< ::boost::mp11::mp_map_find > + >; +}; + +template +struct normalize_deduced_impl +{ + template + using apply = T; +}; + +template class F, class... T> +struct normalize_deduced_impl< ::boost::type_erasure::deduced > > +{ + template + using apply = typename ::boost::type_erasure::deduced...> >::type; +}; + +template<> +struct normalize_placeholder_impl +{ + template + using apply = typename ::boost::type_erasure::detail::normalize_deduced_impl::template apply; +}; + +template +using normalize_placeholder = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_placeholder_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 +struct create_placeholder_map +{ + template + using transform_one = ::boost::mpl::pair< + typename ::boost::mpl::first

::type, + ::boost::type_erasure::detail::normalize_placeholder_t< + M, + typename ::boost::mpl::second

::type + > + >; + typedef ::boost::mp11::mp_transform< + transform_one, + M + > type; +}; + +template +using create_placeholder_map_t = typename ::boost::type_erasure::detail::create_placeholder_map::type; + +template +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 > result; + typedef ::boost::mp11::mp_map_insert > type; + BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find >, result>)); +}; + +template +struct convert_deduced_f +{ + template + using apply = typename ::boost::type_erasure::detail::convert_deduced::type; +}; + +template +using convert_deductions_t = + ::boost::mp11::mp_fold< + M, + ::boost::type_erasure::detail::make_mp_list, + ::boost::type_erasure::detail::convert_deduced_f::template apply + >; + +template +using convert_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::convert_deductions_t >; + +template +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 > type; + BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find >, result>)); +}; + +template +struct add_deduced_f +{ + template + using apply = typename ::boost::type_erasure::detail::add_deduced::type; +}; + +template +using add_deductions_t = + ::boost::mp11::mp_fold< + M, + ::boost::type_erasure::detail::make_mp_list, + ::boost::type_erasure::detail::add_deduced_f< + ::boost::type_erasure::detail::make_mp_list + >::template apply + >; + +template +using add_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::add_deductions_t >; + +// Fold Op for normalize_concept_impl +template +struct insert_concept_impl +{ + template + using apply = + ::boost::mpl::pair< + ::boost::mp11::mp_set_push_back, + typename Out::second + >; +}; + +template +using mpl_insert = typename ::boost::mpl::insert::type; + +template +using insert_concept_same_type = + ::boost::mpl::pair< + typename Out::first, + typename ::boost::type_erasure::detail::eval_if< + ::boost::is_same::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 +struct insert_concept_impl< ::boost::type_erasure::same_type > +{ + template + 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 +struct normalize_concept_impl_test; + +template +using normalize_concept_impl_f = + typename ::boost::type_erasure::detail::normalize_concept_impl_test< + ::boost::mpl::is_sequence::value + >::template apply; + +template<> +struct normalize_concept_impl_test +{ + template + using apply = + ::boost::mp11::mp_fold< + ::boost::type_erasure::detail::make_mp_list, + Out, + ::boost::type_erasure::detail::normalize_concept_impl_f + >; +}; + +template<> +struct normalize_concept_impl_test +{ + template + using apply = typename ::boost::type_erasure::detail::insert_concept_impl::template apply; +}; + +template +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 +using normalize_concept_impl = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_impl_t >; + +template +using get_all_placeholders_impl = typename ::boost::type_erasure::detail::get_placeholders::type; + +template +using get_all_placeholders = + ::boost::mp11::mp_fold< + Seq, + ::boost::mp11::mp_list<>, + ::boost::type_erasure::detail::get_all_placeholders_impl + >; + +template +using make_identity_pair = ::boost::mpl::pair; + +template +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::first + > + >; + +template +using append_type_info = ::boost::mp11::mp_set_push_back< + S, + ::boost::type_erasure::typeid_ +>; + +template +using add_typeinfo_t = + ::boost::mp11::mp_fold< + get_all_placeholders, + Seq, + ::boost::type_erasure::detail::append_type_info + >; + +// Seq should be a flattened mp_list sequence of leaf concepts. +// adds typeid_

for every placeholder used. +template +using add_typeinfo = ::boost::mpl::identity >; + +template +struct normalize_concept_substitute_f +{ + template + using apply = ::boost::mp11::mp_set_push_back::type + >; +}; + +template +using normalize_concept_adjustments = + ::boost::type_erasure::detail::eval_if< + ::boost::type_erasure::is_relaxed::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 +using get_placeholder_normalization_map_t = + ::boost::type_erasure::detail::create_placeholder_map_t< + typename normalize_concept_impl_t::second + >; + +template +using get_placeholder_normalization_map = + ::boost::type_erasure::detail::create_placeholder_map< + typename normalize_concept_impl_t::second + >; + +// Flattens a Concept to an mpl::vector of primitive +// concepts. Resolves same_type and deduced placeholders. +template +using normalize_concept_t = + ::boost::type_erasure::detail::normalize_concept_adjustments< + Concept, + boost::type_erasure::detail::normalize_concept_impl_t + >; + +template +using normalize_concept = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_t >; + +template +struct collect_concepts_f; + +template +using collect_concepts_recursive = ::boost::mp11::mp_fold< + ::boost::type_erasure::detail::make_mp_list, + Out, + ::boost::type_erasure::detail::collect_concepts_f::template apply +>; + +template +using collect_concepts_impl = + ::boost::type_erasure::detail::eval_if< ::boost::is_same::value, + ::boost::type_erasure::detail::first, + ::boost::mp11::mp_set_push_front, + ::boost::type_erasure::detail::eval_if< ::boost::mpl::is_sequence::value, + ::boost::type_erasure::detail::collect_concepts_recursive, + ::boost::type_erasure::detail::first, + Out, + Concept, + Map + >, + Transformed + >; + +template::second + >, + class Out = ::boost::mp11::mp_list<> +> +using collect_concepts_t = + collect_concepts_impl::type + >; + +template +struct collect_concepts_f +{ + template + using apply = ::boost::type_erasure::detail::collect_concepts_t; +}; + +// Returns an MPL sequence containing all the concepts +// in Concept. If Concept is considered as a DAG, +// the result will be sorted topologically. +template +using collect_concepts = ::boost::mpl::identity< + ::boost::type_erasure::detail::collect_concepts_t >; + +#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 #include #include +#include + +#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 #include #include #include @@ -34,10 +35,23 @@ struct get_null_vtable_entry { typename ::boost::remove_pointer::type> type; }; +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES + #define BOOST_PP_FILENAME_1 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) #include BOOST_PP_ITERATE() +#else + +template +struct null_throw { + 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 #include #include +#include #include namespace boost { @@ -48,6 +49,132 @@ struct identity typedef T type; }; +template +struct vtable_adapter; + +#ifdef BOOST_TYPE_ERASURE_USE_MP11 + +template +using rebind_placeholders_t = typename rebind_placeholders::type; + +template +using rebind_one_placeholder = ::boost::mp11::mp_second< ::boost::mp11::mp_map_find >; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = ::boost::type_erasure::detail::eval_if< + ::boost::mp11::mp_map_contains::value, + ::boost::type_erasure::detail::rebind_one_placeholder, + ::boost::type_erasure::detail::first, + T, + Bindings + >; +}; + +template +using rebind_placeholders_in_argument_t = typename ::boost::type_erasure::detail::rebind_placeholders_in_argument_impl::template apply; + +template +using rebind_placeholders_in_argument = ::boost::mpl::identity< ::boost::type_erasure::detail::rebind_placeholders_in_argument_t >; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = rebind_placeholders_in_argument_t&; +}; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = rebind_placeholders_in_argument_t&&; +}; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = rebind_placeholders_in_argument_t const; +}; + +template +using rebind_placeholders_in_deduced = + typename ::boost::type_erasure::deduced< + ::boost::type_erasure::detail::rebind_placeholders_t + >::type; + +template +using rebind_deduced_placeholder = + ::boost::mp11::mp_second< + ::boost::mp11::mp_map_find > + >; + +template +struct rebind_placeholders_in_argument_impl< + ::boost::type_erasure::deduced +> +{ + template + using apply = ::boost::type_erasure::detail::eval_if< + ::boost::mp11::mp_map_contains >::value, + ::boost::type_erasure::detail::rebind_deduced_placeholder, + ::boost::type_erasure::detail::rebind_placeholders_in_deduced, + F, + Bindings + >; +}; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = + rebind_placeholders_in_argument_t + (rebind_placeholders_in_argument_t...); +}; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = + rebind_placeholders_in_argument_t + (rebind_placeholders_in_argument_t::*) + (rebind_placeholders_in_argument_t...); +}; + +template +struct rebind_placeholders_in_argument_impl +{ + template + using apply = + rebind_placeholders_in_argument_t + (rebind_placeholders_in_argument_t::*) + (rebind_placeholders_in_argument_t...) const; +}; + +template class T, class... U, class Bindings> +struct rebind_placeholders, Bindings> +{ + typedef ::boost::type_erasure::detail::make_mp_list xBindings; + typedef T...> type; +}; + +template +struct rebind_placeholders, Bindings> +{ + typedef ::boost::type_erasure::detail::make_mp_list xBindings; + typedef vtable_adapter< + rebind_placeholders_t, + rebind_placeholders_in_argument_t + > type; +}; + +#else + template struct rebind_placeholders_in_argument { @@ -62,6 +189,15 @@ struct rebind_placeholders_in_argument >::type type; }; +template +struct rebind_placeholders, Bindings> +{ + typedef vtable_adapter< + typename rebind_placeholders::type, + typename rebind_placeholders_in_argument::type + > type; +}; + template struct rebind_placeholders_in_argument { @@ -134,6 +270,26 @@ struct rebind_placeholders_in_argument >::type type(typename rebind_placeholders_in_argument::type...); }; +template +struct rebind_placeholders_in_argument +{ + typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument< + R, + Bindings + >::type (rebind_placeholders_in_argument::type::*type) + (typename rebind_placeholders_in_argument::type...); +}; + +template +struct rebind_placeholders_in_argument +{ + typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument< + R, + Bindings + >::type (rebind_placeholders_in_argument::type::*type) + (typename rebind_placeholders_in_argument::type...) const; +}; + #else #define BOOST_PP_FILENAME_1 @@ -142,6 +298,8 @@ struct rebind_placeholders_in_argument #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 #include -#include +#include #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES # include // 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 - explicit storage(T&& arg) : data(new typename remove_cv< - typename remove_reference::type>::type(std::forward(arg))) {} + explicit storage(T&& arg) : data(new typename boost::decay::type(std::forward(arg))) {} #else template - explicit storage(const T& arg) : data(new T(arg)) {} + explicit storage(const T& arg) : data(new typename boost::decay::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 #include #include +#include #include #include #include @@ -98,7 +99,7 @@ struct compare_vtable; template<> struct compare_vtable<> { template - 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 - 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 - 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, ~); } }; diff --git a/boost/type_erasure/dynamic_any_cast.hpp b/boost/type_erasure/dynamic_any_cast.hpp index 01aa2b6ef9..6f0939e00d 100644 --- a/boost/type_erasure/dynamic_any_cast.hpp +++ b/boost/type_erasure/dynamic_any_cast.hpp @@ -96,13 +96,21 @@ R dynamic_any_cast_impl(Any& arg, const static_binding& map) >::type normalized; typedef typename ::boost::mpl::fold< normalized, +#ifndef BOOST_TYPE_ERASURE_USE_MP11 ::boost::mpl::set0<>, +#else + ::boost::mp11::mp_list<>, +#endif ::boost::type_erasure::detail::get_placeholders< ::boost::mpl::_2, ::boost::mpl::_1 > >::type placeholders; +#ifndef BOOST_TYPE_ERASURE_USE_MP11 typedef ::boost::type_erasure::detail::substitution_map< ::boost::mpl::map0<> > identity_map; +#else + typedef ::boost::type_erasure::detail::make_identity_placeholder_map identity_map; +#endif ::boost::type_erasure::dynamic_binding my_binding( ::boost::type_erasure::binding_of(arg), ::boost::type_erasure::make_binding()); @@ -153,7 +161,7 @@ R dynamic_any_cast_impl(Any& arg, const static_binding& map) * * \throws bad_any_cast if the concepts used by R were * not previously registered via a call to - * @ref register_binding. + * \register_binding. * * Example: * \code diff --git a/boost/type_erasure/free.hpp b/boost/type_erasure/free.hpp index a2a6a7100a..23d1a67856 100644 --- a/boost/type_erasure/free.hpp +++ b/boost/type_erasure/free.hpp @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -148,6 +151,64 @@ struct first_placeholder_index : } \ } +/** INTERNAL ONLY */ +#define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name, N)\ + BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name, N) + +#ifdef BOOST_TYPE_ERASURE_DOXYGEN + +/** + * \brief Defines a primitive concept for a free function. + * + * \param concept_name is the name of the concept to declare. + * If it is omitted it defaults to has_ ## function_name + * \param function_name is the name of the function. + * + * The declaration of the concept is + * \code + * template + * struct concept_name; + * \endcode + * where Sig is a function type giving the + * signature of the function. + * + * This macro can only be used at namespace scope. + * + * Example: + * + * \code + * BOOST_TYPE_ERASURE_FREE(to_string) + * typedef has_to_string to_string_concept; + * \endcode + * + * In C++03, the macro can only be used in the global namespace and + * is defined as: + * + * \code + * #define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) + * \endcode + * + * Example: + * + * \code + * BOOST_TYPE_ERASURE_FREE((boost)(has_to_string), to_string, 1) + * \endcode + * + * For backwards compatibility, this form is always accepted. + */ +#define BOOST_TYPE_ERASURE_FREE(concept_name, function_name) + +#else + +#define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) \ + BOOST_TYPE_ERASURE_FREE_I( \ + qualified_name, \ + BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ + function_name, \ + N) + +#endif + #else namespace boost { @@ -208,12 +269,143 @@ struct make_index_list<0> { typedef index_list<> type; }; -} -} -} +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \ + !defined(BOOST_NO_CXX11_DECLTYPE) + +template +using make_index_list_t = typename ::boost::type_erasure::detail::make_index_list::type; + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1900) + +template +struct first_placeholder_index_ : + ::boost::type_erasure::detail::first_placeholder_index< + ::boost::remove_cv_t< ::boost::remove_reference_t >... + > +{}; +template +using first_placeholder_index_t = + typename ::boost::type_erasure::detail::first_placeholder_index_::type; + +#else + +template +using first_placeholder_index_t = + typename ::boost::type_erasure::detail::first_placeholder_index< + ::boost::remove_cv_t< ::boost::remove_reference_t >... + >::type; + +#endif + +template +using free_param_t = + typename ::boost::mpl::eval_if_c<(::boost::type_erasure::detail::first_placeholder_index_t::value == I), + ::boost::type_erasure::detail::maybe_const_this_param, \ + ::boost::type_erasure::as_param + >::type; + +template +struct free_interface_chooser +{ + template class C, template class F> + using apply = Base; +}; + +template +struct free_interface_chooser< + R(A...), + typename ::boost::type_erasure::detail::first_placeholder< + ::boost::remove_cv_t< ::boost::remove_reference_t >...>::type> +{ + template class C, template class F> + using apply = F >; +}; + +template class C, template class F> +struct free_choose_interface { + template + using apply = typename free_interface_chooser::template apply; +}; /** INTERNAL ONLY */ -#define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name, N) \ +#define BOOST_TYPE_ERASURE_FREE_I(concept_name, function_name) \ +template \ +struct concept_name; \ + \ +namespace boost_type_erasure_impl { \ + \ +template \ +struct concept_name ## _free_interface; \ +template \ +struct concept_name ## _free_interface > : Base {\ + friend ::boost::type_erasure::rebind_any_t \ + function_name( \ + ::boost::type_erasure::detail::free_param_t... t) \ + { \ + return ::boost::type_erasure::call( \ + concept_name(), \ + std::forward< ::boost::type_erasure::detail::free_param_t >(t)...);\ + } \ +}; \ + \ +template \ +struct concept_name ## free; \ + \ +template \ +struct concept_name ## free { \ + static R apply(T... t) \ + { return function_name(std::forward(t)...); } \ +}; \ + \ +template \ +struct concept_name ## free { \ + static void apply(T... t) \ + { function_name(std::forward(t)...); } \ +}; \ + \ +} \ + \ +template \ +struct concept_name : \ + boost_type_erasure_impl::concept_name##free \ +{}; \ + \ +template \ +::boost::type_erasure::detail::free_choose_interface \ +boost_type_erasure_find_interface(concept_name); + +#define BOOST_TYPE_ERASURE_FREE_SIMPLE(name, ...) \ + BOOST_TYPE_ERASURE_FREE_I(has_ ## name, name) + +#define BOOST_TYPE_ERASURE_FREE_NS_I(concept_name, name) \ + BOOST_TYPE_ERASURE_FREE_I(concept_name, name) + +#define BOOST_TYPE_ERASURE_FREE_NS(concept_name, name) \ + BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \ + BOOST_TYPE_ERASURE_FREE_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_FREE_NAMED(concept_name, name, ...) \ + BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \ + BOOST_TYPE_ERASURE_FREE_NS, \ + BOOST_TYPE_ERASURE_FREE_I) \ + (concept_name, name) + +#define BOOST_TYPE_ERASURE_FREE_CAT(x, y) x y + +#define BOOST_TYPE_ERASURE_FREE(name, ...) \ + BOOST_TYPE_ERASURE_FREE_CAT( \ + BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \ + BOOST_TYPE_ERASURE_FREE_SIMPLE, \ + BOOST_TYPE_ERASURE_FREE_NAMED), \ + (name, __VA_ARGS__)) + +#else + +/** INTERNAL ONLY */ +#define BOOST_TYPE_ERASURE_FREE_II(qual_name, concept_name, function_name) \ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qual_name) \ \ template \ @@ -273,41 +465,23 @@ struct make_index_list<0> { } \ } -#endif /** INTERNAL ONLY */ -#define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name, N)\ - BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name, N) +#define BOOST_TYPE_ERASURE_FREE_I(namespace_name, concept_name, function_name) \ + BOOST_TYPE_ERASURE_FREE_II(namespace_name, concept_name, function_name) -/** - * \brief Defines a primitive concept for a free function. - * - * \param qualified_name should be a preprocessor sequence - * of the form (namespace1)(namespace2)...(concept_name). - * \param function_name is the name of the function. - * \param N is the number of arguments of the function. - * - * The declaration of the concept is - * \code - * template - * struct ::namespace1::namespace2::...::concept_name; - * \endcode - * where Sig is a function type giving the - * signature of the function. - * - * This macro can only be used in the global namespace. - * - * Example: - * - * \code - * BOOST_TYPE_ERASURE_FREE((boost)(has_to_string), to_string, 1) - * \endcode - */ -#define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, N) \ +#define BOOST_TYPE_ERASURE_FREE(qualified_name, function_name, ...) \ BOOST_TYPE_ERASURE_FREE_I( \ qualified_name, \ BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ - function_name, \ - N) + function_name) + +#endif + +} +} +} + +#endif #endif diff --git a/boost/type_erasure/is_placeholder.hpp b/boost/type_erasure/is_placeholder.hpp index 055ee621ad..a1e67fc165 100644 --- a/boost/type_erasure/is_placeholder.hpp +++ b/boost/type_erasure/is_placeholder.hpp @@ -12,16 +12,27 @@ #define BOOST_TYPE_ERASURE_DETAIL_IS_PLACEHOLDER_HPP_INCLUDED #include -#include -#include namespace boost { namespace type_erasure { +#ifdef BOOST_TYPE_ERASURE_DOXYGEN + /** A metafunction that indicates whether a type is a @ref placeholder. */ template -struct is_placeholder : ::boost::is_base_and_derived {}; +struct is_placeholder {}; + +#else + +template +struct is_placeholder : ::boost::mpl::false_ {}; + +template +struct is_placeholder : + ::boost::mpl::true_ {}; + +#endif } } diff --git a/boost/type_erasure/is_subconcept.hpp b/boost/type_erasure/is_subconcept.hpp index aa8ee6585a..c327731094 100644 --- a/boost/type_erasure/is_subconcept.hpp +++ b/boost/type_erasure/is_subconcept.hpp @@ -11,6 +11,7 @@ #ifndef BOOST_TYPE_ERASURE_IS_SUBCONCEPT_HPP_INCLUDED #define BOOST_TYPE_ERASURE_IS_SUBCONCEPT_HPP_INCLUDED +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -26,10 +28,33 @@ namespace boost { namespace type_erasure { namespace detail { +#ifdef BOOST_TYPE_ERASURE_USE_MP11 + +template +struct mp_set_has_key : ::boost::mp11::mp_set_contains {}; + +template +struct is_subconcept_f +{ + template + using apply = ::boost::mp11::mp_set_contains >; +}; + +template +struct is_subconcept_f +{ + template + using apply = ::boost::mp11::mp_set_contains; +}; + +#endif + template struct is_subconcept_impl { +#ifndef BOOST_TYPE_ERASURE_USE_MP11 typedef typename ::boost::type_erasure::detail::normalize_concept< Super>::concept_set super_set; + typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map< Super >::type placeholder_subs_super; @@ -68,6 +93,30 @@ struct is_subconcept_impl { >::type, typename ::boost::mpl::end::type >::type type; +#else + typedef ::boost::type_erasure::detail::normalize_concept_t super_set; + + typedef ::boost::type_erasure::detail::get_placeholder_normalization_map_t< + Super + > placeholder_subs_super; + + typedef ::boost::type_erasure::detail::normalize_concept_t normalized_sub; + typedef ::boost::type_erasure::detail::get_placeholder_normalization_map_t< + Sub + > placeholder_subs_sub; + typedef ::boost::mp11::mp_eval_if_c< ::boost::is_same::value, + void, + ::boost::type_erasure::detail::convert_deductions_t, + PlaceholderMap, + placeholder_subs_sub, + placeholder_subs_super + > bindings; + + typedef typename ::boost::mp11::mp_all_of< + normalized_sub, + ::boost::type_erasure::detail::is_subconcept_f::template apply + > type; +#endif }; } @@ -92,13 +141,24 @@ struct is_subconcept_impl { * are presumed to use the same set of placeholders. */ template -struct is_subconcept : ::boost::type_erasure::detail::is_subconcept_impl::type { -}; +struct is_subconcept : + ::boost::mpl::and_< + ::boost::type_erasure::detail::check_map, + ::boost::type_erasure::detail::is_subconcept_impl + >::type +{}; #ifndef BOOST_TYPE_ERASURE_DOXYGEN +template +struct is_subconcept : + ::boost::type_erasure::detail::is_subconcept_impl::type +{}; template struct is_subconcept > : - ::boost::type_erasure::detail::is_subconcept_impl::type + ::boost::mpl::and_< + ::boost::type_erasure::detail::check_map, + ::boost::type_erasure::detail::is_subconcept_impl + >::type {}; #endif diff --git a/boost/type_erasure/member.hpp b/boost/type_erasure/member.hpp index c20a348f47..d358cbad20 100644 --- a/boost/type_erasure/member.hpp +++ b/boost/type_erasure/member.hpp @@ -11,6 +11,10 @@ #ifndef BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED #define BOOST_TYPE_ERASURE_MEMBER_HPP_INCLUDED +#include + +#ifndef BOOST_TYPE_ERASURE_MEMBER + #include #include #include @@ -74,25 +78,54 @@ /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_MEMBER_ARG, ~) +#ifdef BOOST_TYPE_ERASURE_DOXYGEN + /** * \brief Defines a primitive concept for a member function. * - * \param qualified_name should be a preprocessor sequence - * of the form (namespace1)(namespace2)...(concept_name). + * \param concept_name is the name of the concept to declare. + * If it is omitted it defaults to has_ ## member * \param member is the name of the member function. - * \param N is the number of arguments of the function. * * The declaration of the concept is * \code * template - * struct ::namespace1::namespace2::...::concept_name; + * struct concept_name; + * \endcode + * where @c Sig is a function type giving the + * signature of the member function, and @c T is the + * object type. @c T may be const-qualified for + * const member functions. @c concept_name + * is an alias for @c concept_name. + * + * This macro can only be used at namespace scope. + * + * Example: + * + * \code + * namespace boost { + * BOOST_TYPE_ERASURE_MEMBER(push_back) + * } + * typedef boost::has_push_back push_back_concept; + * \endcode + * + * The concept defined by this function may be specialized to + * provide a concept_map. The class object will be passed by + * reference as the first parameter. + * + * \code + * template<> + * struct has_push_back > { + * static void apply(std::list& l, int i) { l.push_back(i); } + * }; * \endcode - * where Sig is a function type giving the - * signature of the member function, and T is the - * object type. T may be const-qualified for - * const member functions. * - * This macro can only be used in the global namespace. + * In C++03, the macro can only be used in the global namespace and + * is defined as: + * + * \code + * #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) + * \endcode * * Example: * @@ -101,9 +134,12 @@ * typedef boost::has_push_back push_back_concept; * \endcode * - * \note In C++11 the argument N is ignored and may be omitted. - * BOOST_TYPE_ERASURE_MEMBER will always define a variadic concept. + * For backwards compatibility, this form is always accepted. */ +#define BOOST_TYPE_ERASURE_MEMBER(concept_name, member) /**/ + +#else + #define BOOST_TYPE_ERASURE_MEMBER(qualified_name, member, N) \ BOOST_TYPE_ERASURE_MEMBER_I( \ qualified_name, \ @@ -111,6 +147,8 @@ member, \ N) +#endif + #else /** INTERNAL ONLY */ @@ -119,9 +157,14 @@ #define BOOST_TYPE_ERASURE_MEMBER_TPL_ARG_LIST(N, X) , class... A #define BOOST_TYPE_ERASURE_MEMBER_ENUM_PARAMS(N, X) X... -#define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward(x)... +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +# define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward(x)... +# define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward::type>(a)... +#else +# define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) x... +# define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , a... +#endif #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_PARAMS(N, X) , X... -#define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward::type>(a)... #define BOOST_TYPE_ERASURE_MEMBER_ENUM_TRAILING_BINARY_PARAMS(N, X, x) , X... x #define BOOST_TYPE_ERASURE_MEMBER_ENUM_ARGS(N) typename ::boost::type_erasure::as_param::type... a @@ -242,3 +285,5 @@ BOOST_TYPE_ERASURE_MEMBER_II(namespace_name, concept_name, member, N) #endif + +#endif diff --git a/boost/type_erasure/operators.hpp b/boost/type_erasure/operators.hpp index 97fddbfbc6..059f41e091 100644 --- a/boost/type_erasure/operators.hpp +++ b/boost/type_erasure/operators.hpp @@ -28,9 +28,6 @@ namespace boost { namespace type_erasure { -template -class any; - /** INTERNAL ONLY */ #define BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op) \ template \ diff --git a/boost/type_erasure/param.hpp b/boost/type_erasure/param.hpp index e3cce05898..7aca5e3c6b 100644 --- a/boost/type_erasure/param.hpp +++ b/boost/type_erasure/param.hpp @@ -27,12 +27,16 @@ namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN + template class any; template class binding; +#endif + namespace detail { struct access; @@ -75,16 +79,6 @@ struct placeholder_conversion : boost::mpl::true_ {}; } -#ifdef __clang__ -#if !__has_feature(cxx_reference_qualified_functions) -/** INTERNAL ONLY */ -#define BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS -#endif -#else -/** INTERNAL ONLY */ -#define BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS -#endif - /** * \brief A wrapper to help with overload resolution for functions * operating on an @ref any. @@ -96,8 +90,8 @@ struct placeholder_conversion : boost::mpl::true_ {}; * with an @ref any that has the same @c Concept * and base placeholder when there exists a corresponding * standard conversion for the placeholder. - * A conversion sequence from @ref any to @ref param is - * a better conversion sequence than @ref any to @ref param + * A conversion sequence from @ref any "any" to @ref param "param" is + * a better conversion sequence than @ref any "any" to @ref param "param" * iff the corresponding placeholder standard conversion * sequence from P to P1 is a better conversion sequence than * P to P2. @@ -172,13 +166,19 @@ public: {} #endif + /** INTERNAL ONLY */ + param(const ::boost::type_erasure::detail::storage& data, + const ::boost::type_erasure::binding& table) + : _impl(data, table) + {} + /** Returns the stored @ref any. */ any get() const { return _impl; } private: any _impl; }; -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) && !defined(BOOST_TYPE_ERASURE_DOXYGEN) template class param { @@ -199,7 +199,21 @@ public: param(U& u, typename boost::enable_if< ::boost::is_same > >::type* = 0) : _impl(u) {} any get() const { return _impl; } protected: - any _impl; + struct _impl_t { + _impl_t(const ::boost::type_erasure::detail::storage& data_, + const ::boost::type_erasure::binding& table_) + : table(table_), data(data_) + {} + _impl_t(const any& u) + : table(::boost::type_erasure::detail::access::table(u)), + data(::boost::type_erasure::detail::access::data(u)) + {} + // It's safe to capture the table by reference, because + // the user's argument should out-live us. storage is + // just a void*, so we don't need to add indirection. + const ::boost::type_erasure::binding& table; + ::boost::type_erasure::detail::storage data; + } _impl; }; template @@ -257,7 +271,7 @@ public: /** * \brief Metafunction that creates a @ref param. * - * If @c T is a (cv/reference qualifed) placeholder, + * If @c T is a (cv/reference qualified) placeholder, * returns @ref param<@ref concept_of "concept_of::type", T>, * otherwise, returns T. This metafunction is intended * to be used for function arguments in specializations of @@ -280,6 +294,13 @@ struct as_param { #endif }; +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES + +template +using as_param_t = typename ::boost::type_erasure::as_param::type; + +#endif + } } diff --git a/boost/type_erasure/placeholder.hpp b/boost/type_erasure/placeholder.hpp index 0ea7ab5bce..1311f03bae 100644 --- a/boost/type_erasure/placeholder.hpp +++ b/boost/type_erasure/placeholder.hpp @@ -45,7 +45,10 @@ namespace type_erasure { * explicitly, but the substitution still works the * same way. */ -struct placeholder {}; +struct placeholder { + /// INTERNAL ONLY + typedef void _boost_type_erasure_is_placeholder; +}; struct _a : placeholder {}; struct _b : placeholder {}; diff --git a/boost/type_erasure/placeholder_of.hpp b/boost/type_erasure/placeholder_of.hpp index 8e8171898d..4a42b5744d 100644 --- a/boost/type_erasure/placeholder_of.hpp +++ b/boost/type_erasure/placeholder_of.hpp @@ -14,12 +14,16 @@ namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN + template class any; template class param; +#endif + /** * A metafunction returning the (const/reference qualified) placeholder * corresponding to an @ref any. It will also work for all bases @@ -52,6 +56,13 @@ struct placeholder_of< ::boost::type_erasure::param > typedef T type; }; +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES + +template +using placeholder_of_t = typename ::boost::type_erasure::placeholder_of::type; + +#endif + } } diff --git a/boost/type_erasure/rebind_any.hpp b/boost/type_erasure/rebind_any.hpp index 452e6893d8..be62cff723 100644 --- a/boost/type_erasure/rebind_any.hpp +++ b/boost/type_erasure/rebind_any.hpp @@ -20,8 +20,10 @@ namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN template class any; +#endif /** * A metafunction that changes the @ref placeholder of @@ -36,6 +38,7 @@ class any; * \code * rebind_any, _a>::type -> any * rebind_any, _b&>::type -> any + * rebind_any, _c&&>::type -> any * rebind_any, int>::type -> int * \endcode * @@ -62,6 +65,13 @@ struct rebind_any #endif }; +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES + +template +using rebind_any_t = typename ::boost::type_erasure::rebind_any::type; + +#endif + } } diff --git a/boost/type_erasure/register_binding.hpp b/boost/type_erasure/register_binding.hpp index 46364c9775..b0489b3ef0 100644 --- a/boost/type_erasure/register_binding.hpp +++ b/boost/type_erasure/register_binding.hpp @@ -53,7 +53,11 @@ struct append_to_key_static { append_to_key_static(key_type* k) : key(k) {} template void operator()(P) { +#ifndef BOOST_TYPE_ERASURE_USE_MP11 key->push_back(&typeid(typename ::boost::mpl::at::type)); +#else + key->push_back(&typeid(::boost::mp11::mp_second< ::boost::mp11::mp_map_find >)); +#endif } key_type* key; }; @@ -94,7 +98,11 @@ struct register_function { template void operator()(F) { key_type key; +#ifndef BOOST_TYPE_ERASURE_USE_MP11 typedef typename ::boost::type_erasure::detail::get_placeholders >::type placeholders; +#else + typedef typename ::boost::type_erasure::detail::get_placeholders >::type placeholders; +#endif typedef typename ::boost::mpl::fold< placeholders, ::boost::mpl::map0<>, @@ -111,7 +119,7 @@ struct register_function { /** * Registers a model of a concept to allow downcasting @ref any - * via @ref dynamic_any_cast. + * via \dynamic_any_cast. */ template void register_binding(const static_binding&) @@ -140,7 +148,11 @@ void register_binding() typedef typename normalized::first basic; typedef typename ::boost::mpl::fold< basic, +#ifndef BOOST_TYPE_ERASURE_USE_MP11 ::boost::mpl::set0<>, +#else + ::boost::mp11::mp_list<>, +#endif ::boost::type_erasure::detail::get_placeholders< ::boost::mpl::_2, ::boost::mpl::_1> >::type all_placeholders; // remove deduced placeholders diff --git a/boost/type_erasure/relaxed.hpp b/boost/type_erasure/relaxed.hpp index 69e57ec7cd..a9ada91df6 100644 --- a/boost/type_erasure/relaxed.hpp +++ b/boost/type_erasure/relaxed.hpp @@ -52,7 +52,7 @@ struct is_relaxed_impl : * - A raw value can be assigned to an @ref any. This will replace * the value stored by the @ref any. (But note that if @ref assignable * is present, it takes priority.) - * - copy assignment of @ref any uses the copy constructor if it can't + * - assignment of @ref any uses the constructor if it can't * use @ref assignable (either because @ref assignable is missing, * or because the stored types do not match). * - default construction of @ref any is allowed and creates a null any. diff --git a/boost/type_erasure/require_match.hpp b/boost/type_erasure/require_match.hpp index eada5eb7e6..8da4c6b827 100644 --- a/boost/type_erasure/require_match.hpp +++ b/boost/type_erasure/require_match.hpp @@ -32,8 +32,10 @@ namespace boost { namespace type_erasure { +#ifndef BOOST_TYPE_ERASURE_DOXYGEN template class binding; +#endif #ifdef BOOST_TYPE_ERASURE_DOXYGEN @@ -114,6 +116,8 @@ void require_match( ::boost::type_erasure::detail::require_match_impl(cond, table, op, ::std::forward(arg)...); } +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + template void require_match( const Op& op, @@ -129,6 +133,25 @@ void require_match( #else +template +void require_match( + const Op& op, + U&&... arg) +{ + ::boost::type_erasure::is_relaxed< + ::boost::type_erasure::detail::extract_concept_t< + ::boost::type_erasure::detail::get_args_t< + typename ::boost::type_erasure::detail::get_signature::type + >, + ::boost::mp11::mp_list< ::boost::remove_reference_t...> > + > cond; + ::boost::type_erasure::detail::require_match_impl(cond, op, ::std::forward(arg)...); +} + +#endif + +#else + #define BOOST_PP_FILENAME_1 #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY) #include BOOST_PP_ITERATE() diff --git a/boost/type_erasure/static_binding.hpp b/boost/type_erasure/static_binding.hpp index 2da86ca3bc..371ac62e4c 100644 --- a/boost/type_erasure/static_binding.hpp +++ b/boost/type_erasure/static_binding.hpp @@ -21,7 +21,7 @@ namespace type_erasure { * \pre @c Map must be an MPL map whose keys are placeholders. */ template -struct static_binding {}; +struct static_binding { typedef Map map_type; }; /** * A convenience function to prevent constructor calls -- cgit v1.2.3