diff options
Diffstat (limited to 'boost/type_erasure/any.hpp')
-rw-r--r-- | boost/type_erasure/any.hpp | 1108 |
1 files changed, 961 insertions, 147 deletions
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 <algorithm> +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +# include <utility> // std::forward, std::move +#endif #include <boost/config.hpp> #include <boost/utility/enable_if.hpp> #include <boost/utility/addressof.hpp> @@ -20,7 +23,8 @@ #include <boost/mpl/or.hpp> #include <boost/mpl/pair.hpp> #include <boost/mpl/map.hpp> -#include <boost/mpl/fold.hpp> +#include <boost/mpl/reverse_fold.hpp> +#include <boost/type_traits/decay.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/is_same.hpp> @@ -44,9 +48,18 @@ #include <boost/type_erasure/relaxed.hpp> #include <boost/type_erasure/param.hpp> +#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<class Sig> struct constructible; @@ -56,17 +69,48 @@ struct destructible; template<class T, class U> struct assignable; +#endif + namespace detail { +#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +template<class Concept, class Base, class ID> +struct choose_concept_interface +{ + typedef ::boost::type_erasure::concept_interface<Concept, Base, ID> type; +}; + +#else + +struct default_concept_interface +{ + template<class Concept, class Base, class ID> + using apply = ::boost::type_erasure::concept_interface<Concept, Base, ID>; +}; + +default_concept_interface boost_type_erasure_find_interface(...); + +template<class Concept, class Base, class ID> +struct choose_concept_interface +{ + typedef decltype(boost_type_erasure_find_interface(::boost::declval<Concept>())) finder; + typedef typename finder::template apply<Concept, Base, ID> type; +}; + +#endif + +#ifndef BOOST_TYPE_ERASURE_USE_MP11 + template<class Derived, class Concept, class T> 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<Derived>, - ::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<class ID> +struct compute_bases_f +{ + template<class Concept, class Base> + using apply = typename ::boost::type_erasure::detail::choose_concept_interface<Concept, Base, ID>::type; +}; + +template<class Derived, class Concept, class T> +using compute_bases_t = + ::boost::mp11::mp_reverse_fold< + typename ::boost::type_erasure::detail::collect_concepts_t< + Concept + >, + ::boost::type_erasure::any_base<Derived>, + ::boost::type_erasure::detail::compute_bases_f<T>::template apply + >; + +template<class Derived, class Concept, class T> +using compute_bases = ::boost::mpl::identity< ::boost::type_erasure::detail::compute_bases_t<Derived, Concept, T> >; + +#endif + template<class T> T make(T*) { return T(); } @@ -90,6 +158,22 @@ no check_overload(const void*); struct fallback {}; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template<class T> +fallback make_fallback(T&&, boost::mpl::false_) +{ + return fallback(); +} + +template<class T> +T&& make_fallback(T&& arg, boost::mpl::true_) +{ + return std::forward<T>(arg); +} + +#else + template<class T> fallback make_fallback(const T&, boost::mpl::false_) { @@ -102,20 +186,470 @@ const T& make_fallback(const T& arg, boost::mpl::true_) return arg; } +#endif + template<class T> struct is_any : ::boost::mpl::false_ {}; template<class Concept, class T> struct is_any<any<Concept, T> > : ::boost::mpl::true_ {}; +#ifdef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS + +template<class Any, class... U> +struct has_constructor : + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval<Any&>(). + _boost_type_erasure_deduce_constructor(::boost::declval<U>()...) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + > +{}; + +template<class Any> +using has_copy_constructor = + ::boost::type_erasure::is_subconcept< + ::boost::type_erasure::constructible< + typename ::boost::type_erasure::placeholder_of<Any>::type(typename ::boost::type_erasure::placeholder_of<Any>::type const&) + >, + typename ::boost::type_erasure::concept_of<Any>::type + >; + +template<class Any> +using has_move_constructor = + ::boost::type_erasure::is_subconcept< + ::boost::type_erasure::constructible< + typename ::boost::type_erasure::placeholder_of<Any>::type(typename ::boost::type_erasure::placeholder_of<Any>::type &&) + >, + typename ::boost::type_erasure::concept_of<Any>::type + >; + +template<class Any> +using has_mutable_copy_constructor = + ::boost::type_erasure::is_subconcept< + ::boost::type_erasure::constructible< + typename ::boost::type_erasure::placeholder_of<Any>::type(typename ::boost::type_erasure::placeholder_of<Any>::type &) + >, + typename ::boost::type_erasure::concept_of<Any>::type + >; + +struct empty {}; + +template<class T> +struct is_binding_arg : ::boost::mpl::false_ {}; +template<class T> +struct is_binding_arg<binding<T> > : ::boost::mpl::true_ {}; +template<class T> +struct is_binding_arg<binding<T>&&> : ::boost::mpl::true_ {}; +template<class T> +struct is_binding_arg<binding<T>&> : ::boost::mpl::true_ {}; +template<class T> +struct is_binding_arg<binding<T> const&> : ::boost::mpl::true_ {}; + +template<class T> +struct is_static_binding_arg : ::boost::mpl::false_ {}; +template<class T> +struct is_static_binding_arg<static_binding<T> > : ::boost::mpl::true_ {}; +template<class T> +struct is_static_binding_arg<static_binding<T>&&> : ::boost::mpl::true_ {}; +template<class T> +struct is_static_binding_arg<static_binding<T>&> : ::boost::mpl::true_ {}; +template<class T> +struct is_static_binding_arg<static_binding<T> const&> : ::boost::mpl::true_ {}; + +template<class T> +struct is_any_arg : ::boost::mpl::false_ {}; +template<class Concept, class T> +struct is_any_arg<any<Concept, T> > : ::boost::mpl::true_ {}; +template<class Concept, class T> +struct is_any_arg<any<Concept, T>&&> : ::boost::mpl::true_ {}; +template<class Concept, class T> +struct is_any_arg<any<Concept, T>&> : ::boost::mpl::true_ {}; +template<class Concept, class T> +struct is_any_arg<any<Concept, T> const&> : ::boost::mpl::true_ {}; + +template<class T> +struct safe_concept_of; +template<class Concept, class T> +struct safe_concept_of<any<Concept, T> > { typedef Concept type; }; +template<class Concept, class T> +struct safe_concept_of<any<Concept, T>&&> { typedef Concept type; }; +template<class Concept, class T> +struct safe_concept_of<any<Concept, T>&> { typedef Concept type; }; +template<class Concept, class T> +struct safe_concept_of<any<Concept, T> const&> { typedef Concept type; }; + +template<class T> +struct safe_placeholder_of; +template<class Concept, class T> +struct safe_placeholder_of<any<Concept, T> > { typedef T type; }; +template<class Concept, class T> +struct safe_placeholder_of<any<Concept, T>&&> { typedef T type; }; +template<class Concept, class T> +struct safe_placeholder_of<any<Concept, T>&> { typedef T type; }; +template<class Concept, class T> +struct safe_placeholder_of<any<Concept, T> const&> { typedef T type; }; + +template<class T> +using safe_placeholder_t = ::boost::remove_cv_t< ::boost::remove_reference_t<typename safe_placeholder_of<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<class Base, class Enable = void> +struct any_constructor_control : Base +{ + using Base::Base; +}; + +template<class Base> +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor<Base>::value && + ::boost::type_erasure::detail::has_move_constructor<Base>::value && + ::boost::type_erasure::detail::has_mutable_copy_constructor<Base>::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<Base&>(*this) = static_cast<Base const&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast<Base&>(*this) = static_cast<Base&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template<class Base> +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor<Base>::value && + !::boost::type_erasure::detail::has_move_constructor<Base>::value && + ::boost::type_erasure::detail::has_mutable_copy_constructor<Base>::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<Base&>(*this) = static_cast<Base const&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast<Base&>(*this) = static_cast<Base&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template<class Base> +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor<Base>::value && + ::boost::type_erasure::detail::has_move_constructor<Base>::value && + !::boost::type_erasure::detail::has_mutable_copy_constructor<Base>::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<Base&>(*this) = static_cast<Base const&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast<Base&>(*this) = static_cast<Base&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template<class Base> +struct any_constructor_control< + Base, + typename boost::enable_if_c< + !::boost::type_erasure::detail::has_copy_constructor<Base>::value && + !::boost::type_erasure::detail::has_move_constructor<Base>::value && + !::boost::type_erasure::detail::has_mutable_copy_constructor<Base>::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<Base&>(*this) = static_cast<Base const&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control & other) { static_cast<Base&>(*this) = static_cast<Base&>(other); return *this; } + any_constructor_control& operator=(any_constructor_control &&) = default; +}; + +template<class Concept, class T> +struct any_constructor_impl : + ::boost::type_erasure::detail::compute_bases< + ::boost::type_erasure::any<Concept, T>, + Concept, + T + >::type +{ + typedef typename ::boost::type_erasure::detail::compute_bases< + ::boost::type_erasure::any<Concept, T>, + Concept, + T + >::type _boost_type_erasure_base; + // Internal constructors + typedef ::boost::type_erasure::binding<Concept> _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<Concept>)); + _boost_type_erasure_data.data = 0; + } + // capturing constructor + template<class U, + typename ::boost::enable_if_c< + !::boost::type_erasure::detail::is_any_arg<U>::value && + !::boost::type_erasure::detail::is_binding_arg<U>::value && + !::boost::type_erasure::detail::is_static_binding_arg<U>::value + >::type* = nullptr + > + any_constructor_impl(U&& data_arg) + : _boost_type_erasure_table(( + BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, ::boost::decay_t<U>), + ::boost::type_erasure::make_binding< + ::boost::mpl::map1< ::boost::mpl::pair<T, ::boost::decay_t<U> > > + >() + )), + _boost_type_erasure_data(std::forward<U>(data_arg)) + {} + template<class U, class Map, + typename ::boost::enable_if_c< + !::boost::type_erasure::detail::is_any_arg<U>::value && + !::boost::type_erasure::detail::is_binding_arg<U>::value && + !::boost::type_erasure::detail::is_static_binding_arg<U>::value + >::type* = nullptr + > + any_constructor_impl(U&& data_arg, const static_binding<Map>& b) + : _boost_type_erasure_table(( + BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map), + b + )), + _boost_type_erasure_data(std::forward<U>(data_arg)) + { + BOOST_MPL_ASSERT((::boost::is_same< + typename ::boost::mpl::at<Map, T>::type, ::boost::decay_t<U> >)); + } + // converting constructor + template<class U, + typename ::boost::enable_if_c< + ::boost::type_erasure::is_subconcept< + Concept, typename ::boost::type_erasure::detail::safe_concept_of<U>::type, + typename ::boost::mpl::if_c< ::boost::is_same<T, ::boost::type_erasure::detail::safe_placeholder_t<U> >::value, + void, + ::boost::mpl::map1< + ::boost::mpl::pair<T, ::boost::type_erasure::detail::safe_placeholder_t<U> > + > + >::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<T, ::boost::type_erasure::detail::safe_placeholder_t<U> >::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<Concept>, +#endif + ::boost::mpl::map1< + ::boost::mpl::pair< + T, + ::boost::type_erasure::detail::safe_placeholder_t<U> + > + > + >::type() + ), + _boost_type_erasure_data(::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? other._boost_type_erasure_deduce_constructor(std::forward<U>(other)) : 0 + ), std::forward<U>(other)) + ) + {} + template<class U, + typename ::boost::enable_if_c< + ::boost::type_erasure::detail::is_any_arg<U>::value + >::type* = nullptr + > + any_constructor_impl(U&& other, const binding<Concept>& 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<U>(other)) : 0 + ), std::forward<U>(other)) + ) + {} + template<class U, class Map, + typename ::boost::enable_if_c< + ::boost::type_erasure::is_subconcept< + Concept, typename ::boost::type_erasure::detail::safe_concept_of<U>::type, + Map + >::value + >::type* = nullptr + > + any_constructor_impl(U&& other, const static_binding<Map>& 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<U>(other)) : 0 + ), std::forward<U>(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<typename _boost_type_erasure_base::_boost_type_erasure_derived_type const&>(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<typename _boost_type_erasure_base::_boost_type_erasure_derived_type &>(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<typename _boost_type_erasure_base::_boost_type_erasure_derived_type &&>(other)) : 0 + ), std::move(other)) + ) + {} + + template<class R, class... A, class... U> + const _boost_type_erasure_table_type& _boost_type_erasure_extract_table( + ::boost::type_erasure::constructible<R(A...)>*, + U&&... u) + { + return *::boost::type_erasure::detail::extract_table(static_cast<void(*)(A...)>(0), u...); + } + // forwarding constructor + template<class... U, + typename ::boost::enable_if_c< + ::boost::type_erasure::detail::has_constructor<any_constructor_impl, U...>::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>(u)...) : 0, + std::forward<U>(u)... + ) + ), + _boost_type_erasure_data( + ::boost::type_erasure::call( + ::boost::type_erasure::detail::make( + false? this->_boost_type_erasure_deduce_constructor(std::forward<U>(u)...) : 0 + ), + std::forward<U>(u)... + ) + ) + {} + template<class... U, + typename ::boost::enable_if_c< + ::boost::type_erasure::detail::has_constructor<any_constructor_impl, U...>::value + >::type* = nullptr + > + explicit any_constructor_impl(const binding<Concept>& 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>(u)...) : 0 + ), + std::forward<U>(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<typename _boost_type_erasure_base::_boost_type_erasure_derived_type*>(this)->_boost_type_erasure_resolve_assign( + static_cast<const typename _boost_type_erasure_base::_boost_type_erasure_derived_type&>(other)); + return *this; + } + + any_constructor_impl& operator=(any_constructor_impl& other) + { + static_cast<typename _boost_type_erasure_base::_boost_type_erasure_derived_type*>(this)->_boost_type_erasure_resolve_assign( + static_cast<typename _boost_type_erasure_base::_boost_type_erasure_derived_type&>(other)); + return *this; + } + + any_constructor_impl& operator=(any_constructor_impl&& other) + { + static_cast<typename _boost_type_erasure_base::_boost_type_erasure_derived_type*>(this)->_boost_type_erasure_resolve_assign( + static_cast<typename _boost_type_erasure_base::_boost_type_erasure_derived_type&&>(other)); + return *this; + } + + ~any_constructor_impl() + { + _boost_type_erasure_table.template find< + ::boost::type_erasure::destructible<T> + >()(_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<class T> +struct is_rvalue_for_any : + ::boost::mpl::not_< + ::boost::is_lvalue_reference<T> + > +{}; + +template<class C, class P> +struct is_rvalue_for_any<any<C, P> > : + ::boost::mpl::not_< + ::boost::is_lvalue_reference<P> + > +{}; + +} + /** * The class template @ref any can store any object that * models a specific \Concept. It dispatches all @@ -129,16 +663,37 @@ struct is_any<any<Concept, T> > : ::boost::mpl::true_ {}; */ template<class Concept, class T = _self> 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>, Concept, T >::type +#endif { typedef ::boost::type_erasure::binding<Concept> 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<T, U> > + ::boost::mpl::map1< ::boost::mpl::pair<T, U> > >() )), data(data_arg) @@ -224,7 +779,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, typename ::boost::remove_cv<typename ::boost::remove_reference<U>::type>::type), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair<T, typename ::boost::remove_cv<typename ::boost::remove_reference<U>::type>::type> > + ::boost::mpl::map1< ::boost::mpl::pair<T, typename ::boost::remove_cv<typename ::boost::remove_reference<U>::type>::type> > >() )), data(std::forward<U>(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<T, U*> > + ::boost::mpl::map1< ::boost::mpl::pair<T, U*> > >() )), data(data_arg) @@ -307,7 +862,7 @@ public: * * \param other The object to make a copy of. * - * \pre @c Concept must contain @ref constructible<T(const T&)>. + * \pre @c Concept must contain @ref constructible "constructible<T(const T&)>". * \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<Concept2, Tag2>& 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<T(const T&)>. + * \pre @c Concept must contain @ref constructible "constructible<T(const T&)>". * \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<T(const T&)>. + * \pre @c Concept must contain @ref constructible "constructible<T(const T&)>". * \pre The type stored in @c other must match the type expected by * @c binding. * @@ -467,7 +1022,7 @@ public: any(any<Concept2, Tag2>& 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<Concept2, Tag2>&& 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<class R, class... A, class... U> const table_type& _boost_type_erasure_extract_table( @@ -926,7 +1481,7 @@ public: ) {} - // disambiguate + // disambiguating overloads template<class U0, class... U> any(binding<Concept>& 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<class U> + any& operator=(U& other) + { + _boost_type_erasure_resolve_assign(other); + return *this; + } + template<class U> + 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<class U> - any& operator=(const U& other) + any& operator=(U&& other) { - _boost_type_erasure_resolve_assign(other); + _boost_type_erasure_resolve_assign(std::forward<U>(other)); return *this; } +#endif + +#ifndef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS /** * \pre @c Concept includes @ref destructible "destructible<T>". */ ~any() { - table.template find<destructible<T> >()(data); + ::boost::type_erasure::detail::access::table(*this).template find< + ::boost::type_erasure::destructible<T> + >()(::boost::type_erasure::detail::access::data(*this)); } +#endif -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS /** INTERNAL ONLY */ - operator param<Concept, T&>() & { return param<Concept, T&>(data, table); } + operator param<Concept, T&>() & + { + return param<Concept, T&>( + boost::type_erasure::detail::access::data(*this), + boost::type_erasure::detail::access::table(*this)); + } /** INTERNAL ONLY */ - operator param<Concept, T&&>() && { return param<Concept, T&&>(data, table); } + operator param<Concept, T&&>() && { + return param<Concept, T&&>( + 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<class Other> + void _boost_type_erasure_resolve_assign(Other&& other) + { + _boost_type_erasure_assign_impl( + std::forward<Other>(other), + false? this->_boost_type_erasure_deduce_assign( + ::boost::type_erasure::detail::make_fallback( + std::forward<Other>(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval<any&>(). + _boost_type_erasure_deduce_assign(std::forward<Other>(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + ::boost::type_erasure::is_relaxed<Concept>() + ); + } + /** INTERNAL ONLY */ + template<class Other, class U> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + ::boost::mpl::false_) + { + ::boost::type_erasure::call(assignable<T, U>(), *this, std::forward<Other>(other)); + } + /** INTERNAL ONLY */ + template<class Other, class U> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + ::boost::mpl::true_) + { + ::boost::type_erasure::call(assignable<T, U>(), *this, std::forward<Other>(other)); + } + /** INTERNAL ONLY */ + template<class Other> + void _boost_type_erasure_assign_impl( + Other&& other, + const void*, + ::boost::mpl::true_) + { + any temp(std::forward<Other>(other)); + _boost_type_erasure_swap(temp); + } +#else /** INTERNAL ONLY */ template<class Other> - 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<class Other, class U> void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable<T, U>*, ::boost::mpl::false_) { @@ -1060,7 +1709,7 @@ private: /** INTERNAL ONLY */ template<class Other, class U> void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable<T, U>*, ::boost::mpl::true_) { @@ -1069,17 +1718,122 @@ private: /** INTERNAL ONLY */ template<class Other> 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<class Concept2, class Tag2> void _boost_type_erasure_resolve_assign(const any<Concept2, Tag2>& other) { + _boost_type_erasure_resolve_assign_any(other); + } + /** INTERNAL ONLY */ + template<class Concept2, class Tag2> + void _boost_type_erasure_resolve_assign(any<Concept2, Tag2>& other) + { + _boost_type_erasure_resolve_assign_any(other); + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + /** INTERNAL ONLY */ + template<class Concept2, class Tag2> + void _boost_type_erasure_resolve_assign(any<Concept2, Tag2>&& other) + { + _boost_type_erasure_resolve_assign_any(std::move(other)); + } + /** INTERNAL ONLY */ + template<class Other> + void _boost_type_erasure_resolve_assign_any(Other&& other) + { + _boost_type_erasure_assign_impl( + std::forward<Other>(other), + false? this->_boost_type_erasure_deduce_assign( + ::boost::type_erasure::detail::make_fallback( + std::forward<Other>(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval<any&>(). + _boost_type_erasure_deduce_assign(std::forward<Other>(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + false? this->_boost_type_erasure_deduce_constructor( + ::boost::type_erasure::detail::make_fallback( + std::forward<Other>(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval<any&>(). + _boost_type_erasure_deduce_constructor(std::forward<Other>(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + ::boost::type_erasure::is_relaxed<Concept>() + ); + } + /** INTERNAL ONLY */ + template<class Other, class U> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + const void*, + ::boost::mpl::false_) + { + ::boost::type_erasure::call(assignable<T, U>(), *this, std::forward<Other>(other)); + } + /** INTERNAL ONLY */ + template<class Other, class U> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + const void*, + ::boost::mpl::true_) + { + ::boost::type_erasure::call(assignable<T, U>(), *this, std::forward<Other>(other)); + } + /** INTERNAL ONLY */ + template<class Other, class Sig> + void _boost_type_erasure_assign_impl( + Other&& other, + const void*, + const constructible<Sig>*, + ::boost::mpl::true_) + { + any temp(std::forward<Other>(other)); + _boost_type_erasure_swap(temp); + } + /** INTERNAL ONLY */ + template<class Other, class U, class Sig> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + const constructible<Sig>*, + ::boost::mpl::true_) + { + if(::boost::type_erasure::check_match(assignable<T, U>(), *this, other)) // const reference to other is enough! + { + ::boost::type_erasure::unchecked_call(assignable<T, U>(), *this, std::forward<Other>(other)); + } + else + { + any temp(std::forward<Other>(other)); + _boost_type_erasure_swap(temp); + } + } +#else + /** INTERNAL ONLY */ + template<class Other> + void _boost_type_erasure_resolve_assign_any(Other& other) + { _boost_type_erasure_assign_impl( other, false? this->_boost_type_erasure_deduce_assign( @@ -1114,7 +1868,7 @@ private: /** INTERNAL ONLY */ template<class Other, class U> void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable<T, U>*, const void*, ::boost::mpl::false_) @@ -1124,7 +1878,7 @@ private: /** INTERNAL ONLY */ template<class Other, class U> void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable<T, U>*, const void*, ::boost::mpl::true_) @@ -1134,7 +1888,7 @@ private: /** INTERNAL ONLY */ template<class Other, class Sig> void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const void*, const constructible<Sig>*, ::boost::mpl::true_) @@ -1145,7 +1899,7 @@ private: /** INTERNAL ONLY */ template<class Other, class U, class Sig> void _boost_type_erasure_assign_impl( - const Other& other, + Other& other, const assignable<T, U>*, const constructible<Sig>*, ::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<class Concept2, class T2> + friend struct ::boost::type_erasure::any_constructor_impl; +#endif }; template<class Concept, class T> @@ -1209,7 +1969,7 @@ public: : table(( BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, T, U), ::boost::type_erasure::make_binding< - ::boost::mpl::map< ::boost::mpl::pair<T, U> > + ::boost::mpl::map1< ::boost::mpl::pair<T, U> > >() )) { @@ -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<Tag2>::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<class U> + any& operator=(U&& other) + { + _boost_type_erasure_resolve_assign(std::forward<U>(other)); + return *this; + } +#else + template<class U> 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<class U> 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<Concept, T&>() const { return param<Concept, T&>(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<class Other> + void _boost_type_erasure_resolve_assign(Other&& other) + { + _boost_type_erasure_assign_impl( + std::forward<Other>(other), + false? this->_boost_type_erasure_deduce_assign( + ::boost::type_erasure::detail::make_fallback( + std::forward<Other>(other), + ::boost::mpl::bool_< + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval<any&>(). + _boost_type_erasure_deduce_assign(std::forward<Other>(other)) + ) + ) == sizeof(::boost::type_erasure::detail::yes) + >() + ) + ) : 0, + ::boost::mpl::and_< + ::boost::type_erasure::is_relaxed<Concept>, + ::boost::is_convertible<Other, any> +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900)) + , ::boost::mpl::not_< + ::boost::type_erasure::detail::is_rvalue_for_any<Other> + > +#endif + >() + ); + } + /** INTERNAL ONLY */ + template<class Other, class U> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + ::boost::mpl::false_) + { + ::boost::type_erasure::call(assignable<T, U>(), *this, std::forward<Other>(other)); + } + /** INTERNAL ONLY */ + template<class Other, class U> + void _boost_type_erasure_assign_impl( + Other&& other, + const assignable<T, U>*, + ::boost::mpl::true_) + { + if(::boost::type_erasure::check_match(assignable<T, U>(), *this, other)) { + ::boost::type_erasure::unchecked_call(assignable<T, U>(), *this, std::forward<Other>(other)); + } else { + any temp(std::forward<Other>(other)); + _boost_type_erasure_swap(temp); + } + } + /** INTERNAL ONLY */ + template<class Other> + void _boost_type_erasure_assign_impl( + Other&& other, + const void*, + ::boost::mpl::true_) + { + any temp(std::forward<Other>(other)); + _boost_type_erasure_swap(temp); + } +#else /** INTERNAL ONLY */ template<class Other> void _boost_type_erasure_resolve_assign(Other& other) @@ -1525,7 +2346,10 @@ private: >() ) ) : 0, - ::boost::type_erasure::is_relaxed<Concept>() + ::boost::mpl::and_< + ::boost::type_erasure::is_relaxed<Concept>, + ::boost::is_convertible<Other&, any> + >() ); } /** 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<T, U> > + ::boost::mpl::map1< ::boost::mpl::pair<T, U> > >() )) { @@ -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<Concept, const T&>() const { return param<Concept, const T&>(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<T, U> > + ::boost::mpl::map1< ::boost::mpl::pair<T, U> > >() )) { @@ -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<Tag2>::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 + * 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<class U> - any& operator=(U& other) + any& operator=(U&& other) { - _boost_type_erasure_resolve_assign(other); + _boost_type_erasure_resolve_assign(std::forward<U>(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<class U> - any& operator=(const U& other) - { - _boost_type_erasure_resolve_assign(other); - return *this; - } - -#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS /** INTERNAL ONLY */ operator param<Concept, T&&>() const { return param<Concept, T&&>(data, table); } #endif @@ -2141,57 +2933,68 @@ private: } /** INTERNAL ONLY */ template<class Other> - 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>(other), false? this->_boost_type_erasure_deduce_assign( ::boost::type_erasure::detail::make_fallback( - other, + std::forward<Other>(other), ::boost::mpl::bool_< - sizeof( - ::boost::type_erasure::detail::check_overload( - ::boost::declval<any&>(). - _boost_type_erasure_deduce_assign(other) - ) + sizeof( + ::boost::type_erasure::detail::check_overload( + ::boost::declval<any&>(). + _boost_type_erasure_deduce_assign(std::forward<Other>(other)) + ) ) == sizeof(::boost::type_erasure::detail::yes) >() ) ) : 0, - ::boost::type_erasure::is_relaxed<Concept>() + ::boost::mpl::and_< + ::boost::type_erasure::is_relaxed<Concept>, + ::boost::is_convertible<Other, any> + >() ); } /** INTERNAL ONLY */ template<class Other, class U> void _boost_type_erasure_assign_impl( - Other& other, + Other&& other, const assignable<T, U>*, ::boost::mpl::false_) { - ::boost::type_erasure::call(assignable<T, U>(), *this, other); + ::boost::type_erasure::call( + assignable<T, U>(), + // lose rvalueness of this + ::boost::type_erasure::param<Concept, T&>(data, table), + std::forward<Other>(other)); } /** INTERNAL ONLY */ template<class Other, class U> void _boost_type_erasure_assign_impl( - Other& other, + Other&& other, const assignable<T, U>*, ::boost::mpl::true_) { if(::boost::type_erasure::check_match(assignable<T, U>(), *this, other)) { - ::boost::type_erasure::unchecked_call(assignable<T, U>(), *this, other); + ::boost::type_erasure::unchecked_call( + assignable<T, U>(), + // lose rvalueness of this + ::boost::type_erasure::param<Concept, T&>(data, table), + std::forward<Other>(other)); } else { - any temp(other); + any temp(std::forward<Other>(other)); _boost_type_erasure_swap(temp); } } /** INTERNAL ONLY */ template<class Other> void _boost_type_erasure_assign_impl( - Other& other, + Other&& other, const void*, ::boost::mpl::true_) { - any temp(other); + any temp(std::forward<Other>(other)); _boost_type_erasure_swap(temp); } @@ -2202,6 +3005,17 @@ private: #endif +#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES +template<class Concept, class T> +using any_ref = any<Concept, T&>; +template<class Concept, class T> +using any_cref = any<Concept, const T&>; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template<class Concept, class T> +using any_rvref = any<Concept, T&&>; +#endif +#endif + } } |