summaryrefslogtreecommitdiff
path: root/boost/type_erasure
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:12:59 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:12:59 +0900
commitb8cf34c691623e4ec329053cbbf68522a855882d (patch)
tree34da08632a99677f6b79ecb65e5b655a5b69a67f /boost/type_erasure
parent3fdc3e5ee96dca5b11d1694975a65200787eab86 (diff)
downloadboost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.gz
boost-b8cf34c691623e4ec329053cbbf68522a855882d.tar.bz2
boost-b8cf34c691623e4ec329053cbbf68522a855882d.zip
Imported Upstream version 1.67.0upstream/1.67.0
Diffstat (limited to 'boost/type_erasure')
-rw-r--r--boost/type_erasure/any.hpp1108
-rw-r--r--boost/type_erasure/any_cast.hpp2
-rw-r--r--boost/type_erasure/builtin.hpp46
-rw-r--r--boost/type_erasure/call.hpp49
-rw-r--r--boost/type_erasure/check_match.hpp46
-rw-r--r--boost/type_erasure/concept_of.hpp13
-rw-r--r--boost/type_erasure/constructible.hpp6
-rw-r--r--boost/type_erasure/deduced.hpp4
-rw-r--r--boost/type_erasure/derived.hpp7
-rw-r--r--boost/type_erasure/detail/access.hpp105
-rw-r--r--boost/type_erasure/detail/adapt_to_vtable.hpp19
-rw-r--r--boost/type_erasure/detail/any_base.hpp4
-rw-r--r--boost/type_erasure/detail/check_call.hpp72
-rw-r--r--boost/type_erasure/detail/check_map.hpp50
-rw-r--r--boost/type_erasure/detail/dynamic_vtable.hpp22
-rw-r--r--boost/type_erasure/detail/extract_concept.hpp32
-rw-r--r--boost/type_erasure/detail/get_placeholders.hpp102
-rw-r--r--boost/type_erasure/detail/instantiate.hpp60
-rw-r--r--boost/type_erasure/detail/member11.hpp214
-rw-r--r--boost/type_erasure/detail/meta.hpp89
-rw-r--r--boost/type_erasure/detail/normalize.hpp446
-rw-r--r--boost/type_erasure/detail/normalize_deduced.hpp5
-rw-r--r--boost/type_erasure/detail/null.hpp14
-rw-r--r--boost/type_erasure/detail/rebind_placeholders.hpp158
-rw-r--r--boost/type_erasure/detail/storage.hpp7
-rw-r--r--boost/type_erasure/detail/vtable.hpp11
-rw-r--r--boost/type_erasure/dynamic_any_cast.hpp10
-rw-r--r--boost/type_erasure/free.hpp242
-rw-r--r--boost/type_erasure/is_placeholder.hpp17
-rw-r--r--boost/type_erasure/is_subconcept.hpp66
-rw-r--r--boost/type_erasure/member.hpp71
-rw-r--r--boost/type_erasure/operators.hpp3
-rw-r--r--boost/type_erasure/param.hpp51
-rw-r--r--boost/type_erasure/placeholder.hpp5
-rw-r--r--boost/type_erasure/placeholder_of.hpp11
-rw-r--r--boost/type_erasure/rebind_any.hpp10
-rw-r--r--boost/type_erasure/register_binding.hpp14
-rw-r--r--boost/type_erasure/relaxed.hpp2
-rw-r--r--boost/type_erasure/require_match.hpp23
-rw-r--r--boost/type_erasure/static_binding.hpp2
40 files changed, 2916 insertions, 302 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
+
}
}
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<Concept, Tag>& arg)
* \endcode
*
* \pre if @c arg is a pointer, @c T must be a pointer type.
- * \pre @c Concept must contain @ref typeid_<tt>&lt;Tag&gt;</tt>.
+ * \pre @c Concept must contain @ref typeid_ "typeid_<Tag>".
*
* \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 <boost/mpl/vector.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_reference.hpp>
#include <boost/type_erasure/detail/storage.hpp>
#include <boost/type_erasure/placeholder.hpp>
#include <boost/type_erasure/constructible.hpp>
#include <boost/type_erasure/rebind_any.hpp>
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+# include <utility> // std::move
+#endif
#include <typeinfo>
namespace boost {
@@ -64,27 +69,60 @@ struct copy_constructible :
::boost::mpl::vector<constructible<T(const T&)>, destructible<T> >
{};
+#ifdef BOOST_TYPE_ERASURE_DOXYGEN
+
/**
* Enables assignment of @ref any types.
*/
-template<class T = _self, class U = T>
+template<class T = _self, class U = const T&>
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<class T = _self, class U = const T&>
+struct assignable :
+ ::boost::mpl::vector<assignable<T, const U&> >
+{};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+/** INTERNAL ONLY */
+template<class T, class U>
+struct assignable<T, U&&>
+{
+ static void apply(T& dst, U&& src) { dst = std::forward<U>(src); }
+};
+
+#endif
+
+/** INTERNAL ONLY */
+template<class T, class U>
+struct assignable<T, U&>
+{
+ static void apply(T& dst, U& src) { dst = src; }
};
/** INTERNAL ONLY */
template<class T, class U, class Base>
-struct concept_interface<assignable<T, U>, Base, T> : Base
+struct concept_interface<assignable<T, U>, Base, T,
+ typename ::boost::enable_if_c< ::boost::is_reference<U>::value>::type> : Base
{
using Base::_boost_type_erasure_deduce_assign;
assignable<T, U>* _boost_type_erasure_deduce_assign(
- typename ::boost::type_erasure::rebind_any<Base, const U&>::type)
+ typename ::boost::type_erasure::as_param<Base, U>::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 Concept, class Placeholder>
class any;
template<class Concept>
class binding;
+#endif
+
namespace detail {
template<class T>
@@ -293,6 +297,8 @@ namespace detail {
template<class... T>
void ignore(const T&...) {}
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
+
template<class R, class... T, class... U>
const ::boost::type_erasure::binding<
typename ::boost::type_erasure::detail::extract_concept<void(T...), U...>::type>*
@@ -312,6 +318,29 @@ extract_table(R(*)(T...), const U&... arg)
return result;
}
+#else
+
+template<class R, class... T, class... U>
+const ::boost::type_erasure::binding<
+ ::boost::type_erasure::detail::extract_concept_t< ::boost::mp11::mp_list<T...>, ::boost::mp11::mp_list<U...> > >*
+extract_table(R(*)(T...), const U&... arg)
+{
+ const ::boost::type_erasure::binding<
+ ::boost::type_erasure::detail::extract_concept_t<
+ ::boost::mp11::mp_list<T...>, ::boost::mp11::mp_list<U...> > >* result = 0;
+
+ // the order that we run maybe_get_table in doesn't matter
+ ignore(::boost::type_erasure::detail::maybe_get_table(
+ arg,
+ result,
+ ::boost::type_erasure::detail::is_placeholder_arg<T>())...);
+
+ BOOST_ASSERT(result != 0);
+ return result;
+}
+
+#endif
+
template<class Sig, class Args, class Concept, bool ReturnsAny>
struct call_impl_dispatch;
@@ -354,6 +383,8 @@ struct call_impl<R(T...), void(U...), Concept, true> :
{
};
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
+
template<class R, class... T, class... U>
struct call_impl<R(T...), void(U...), void, true> :
::boost::type_erasure::detail::call_impl_dispatch<
@@ -368,6 +399,24 @@ struct call_impl<R(T...), void(U...), void, true> :
{
};
+#else
+
+template<class R, class... T, class... U>
+struct call_impl<R(T...), void(U...), void, true> :
+ ::boost::type_erasure::detail::call_impl_dispatch<
+ R(T...),
+ void(U...),
+ ::boost::type_erasure::detail::extract_concept_t<
+ ::boost::mp11::mp_list<T...>,
+ ::boost::mp11::mp_list< ::boost::remove_reference_t<U>...>
+ >,
+ ::boost::type_erasure::detail::is_placeholder_arg<R>::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<class T>
struct typeid_;
template<class Concept>
class binding;
+#endif
+
namespace detail {
template<class P, class T, class Table>
@@ -94,8 +98,8 @@ bool check_match(const Op& f, U&&... args);
namespace detail {
-template<class Concept>
-bool check_table(const ::boost::type_erasure::binding<Concept>* t, void(*)())
+template<class Concept, class R>
+bool check_table(const ::boost::type_erasure::binding<Concept>* /*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<class T>
+struct get_args;
+
+template<class R, class ... T>
+struct get_args<R(T...)> { typedef ::boost::mp11::mp_list<T...> type; };
+
+template<class Sig>
+using get_args_t = typename get_args<Sig>::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<Op>::type
+ >,
+ ::boost::mp11::mp_list< ::boost::remove_reference_t<U>...> > >* p = 0;
+
+ return ::boost::type_erasure::detail::check_table(
+ p, static_cast<typename ::boost::type_erasure::detail::get_signature<Op>::type*>(0), arg...);
+}
+
+#endif
+
+#else
+
#define BOOST_PP_FILENAME_1 <boost/type_erasure/check_match.hpp>
#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 <boost/config.hpp>
+
namespace boost {
namespace type_erasure {
+#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+
template<class Concept, class T>
class any;
template<class Concept, class T>
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<Concept, T> >
typedef Concept type;
};
+#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
+
+template<class T>
+using concept_of_t = typename ::boost::type_erasure::concept_of<T>::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<class C, class Sig>
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<Tag(T...)>*
_boost_type_erasure_deduce_constructor(
- typename ::boost::type_erasure::as_param<Base, T>::type...)
+ typename ::boost::type_erasure::as_param<Base, T>::type...) const
{
return 0;
}
@@ -168,7 +168,7 @@ struct concept_interface<
using Base::_boost_type_erasure_deduce_constructor;
::boost::type_erasure::constructible<Tag(BOOST_PP_ENUM_PARAMS(N, T))>*
_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<class T>
+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 <boost/type_erasure/detail/storage.hpp>
#include <boost/type_erasure/detail/any_base.hpp>
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \
+ !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, == 1800) && \
+ !BOOST_WORKAROUND(BOOST_GCC, < 40800) && /* Inherited constructors */ \
+ !(defined(__clang_major__) && __clang_major__ == 3 && __clang__minor__ <= 2) /* Inherited constructors */
+#define BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/utility/enable_if.hpp>
+#endif
+
namespace boost {
namespace type_erasure {
@@ -23,6 +35,9 @@ class any;
template<class Concept, class T>
class param;
+template<class Concept>
+class binding;
+
namespace detail {
struct access
@@ -34,11 +49,51 @@ struct access
return static_cast<const Derived&>(arg).table;
}
template<class Concept, class T>
- static const typename any<Concept, T>::table_type&
+ static const ::boost::type_erasure::binding<Concept>&
table(const ::boost::type_erasure::param<Concept, T>& arg)
{
+ return table(arg._impl);
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::binding<Concept>&
+ table(const ::boost::type_erasure::param<Concept, T&>& arg)
+ {
+ return arg._impl.table;
+ }
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template<class Concept, class T>
+ static const ::boost::type_erasure::binding<Concept>&
+ table(const ::boost::type_erasure::param<Concept, T&&>& arg)
+ {
return arg._impl.table;
}
+#endif
+#ifdef BOOST_TYPE_ERASURE_SFINAE_FRIENDLY_CONSTRUCTORS
+ template<class Concept, class T, class = typename ::boost::enable_if_c<!::boost::is_reference<T>::value>::type>
+ static const typename any<Concept, T>::table_type&
+ table(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >& arg)
+ {
+ return static_cast<const ::boost::type_erasure::any<Concept, T>&>(arg)._boost_type_erasure_table;
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >& arg)
+ {
+ return static_cast< ::boost::type_erasure::any<Concept, T>&>(arg)._boost_type_erasure_data;
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >& arg)
+ {
+ return static_cast<const ::boost::type_erasure::any<Concept, T>&>(arg)._boost_type_erasure_data;
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T> >&& arg)
+ {
+ return std::move(static_cast< ::boost::type_erasure::any<Concept, T>&&>(arg)._boost_type_erasure_data);
+ }
+#endif
template<class Derived>
static ::boost::type_erasure::detail::storage&
data(::boost::type_erasure::any_base<Derived>& arg)
@@ -59,6 +114,12 @@ struct access
}
template<class Concept, class T>
static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >& arg)
+ {
+ return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< ::boost::type_erasure::any<Concept, T&>&>(arg).data);
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >& arg)
{
return const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any<Concept, T&>&>(arg).data);
@@ -73,6 +134,12 @@ struct access
static ::boost::type_erasure::detail::storage&
data(::boost::type_erasure::param<Concept, T>& arg)
{
+ return data(arg._impl);
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::param<Concept, T&>& arg)
+ {
return arg._impl.data;
}
template<class Concept, class T>
@@ -85,6 +152,12 @@ struct access
static const ::boost::type_erasure::detail::storage&
data(const ::boost::type_erasure::param<Concept, T>& arg)
{
+ return data(arg._impl);
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(const ::boost::type_erasure::param<Concept, T&>& arg)
+ {
return arg._impl.data;
}
@@ -104,18 +177,48 @@ struct access
}
template<class Concept, class T>
static ::boost::type_erasure::detail::storage&&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&&> >&& arg)
+ {
+ return std::move(static_cast< ::boost::type_erasure::any<Concept, T&&>&>(arg).data);
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&&
data(const ::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&&> >& arg)
{
return std::move(const_cast< ::boost::type_erasure::detail::storage&>(static_cast< const ::boost::type_erasure::any<Concept, T&&>&>(arg).data));
}
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::any_base< ::boost::type_erasure::any<Concept, T&> >&& arg)
+ {
+ return std::move(static_cast< ::boost::type_erasure::any<Concept, T&>&>(arg).data);
+ }
template<class Concept, class T>
static ::boost::type_erasure::detail::storage&&
data(::boost::type_erasure::param<Concept, T>&& arg)
{
+ return std::move(data(arg._impl));
+ }
+ template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&&
+ data(::boost::type_erasure::param<Concept, T&&>&& arg)
+ {
return std::move(arg._impl.data);
}
template<class Concept, class T>
+ static ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::param<Concept, T&>&& arg)
+ {
+ return arg._impl.data;
+ }
+ template<class Concept, class T>
+ static const ::boost::type_erasure::detail::storage&
+ data(::boost::type_erasure::param<Concept, const T&>&& arg)
+ {
+ return arg._impl.data;
+ }
+ template<class Concept, class T>
static ::boost::type_erasure::detail::storage&&
data(::boost::type_erasure::param<Concept, T&&>& arg)
{
diff --git a/boost/type_erasure/detail/adapt_to_vtable.hpp b/boost/type_erasure/detail/adapt_to_vtable.hpp
index e58ddc8599..f842dc3985 100644
--- a/boost/type_erasure/detail/adapt_to_vtable.hpp
+++ b/boost/type_erasure/detail/adapt_to_vtable.hpp
@@ -39,24 +39,9 @@ namespace detail {
template<class T, class Out>
struct get_placeholders;
-template<class T, class Bindings>
-struct rebind_placeholders;
-
-template<class T, class Bindings>
-struct rebind_placeholders_in_argument;
-
template<class PrimitiveConcept, class Sig>
struct vtable_adapter;
-template<class PrimitiveConcept, class Sig, class Bindings>
-struct rebind_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Bindings>
-{
- typedef vtable_adapter<
- typename rebind_placeholders<PrimitiveConcept, Bindings>::type,
- typename rebind_placeholders_in_argument<Sig, Bindings>::type
- > type;
-};
-
template<class PrimitiveConcept, class Sig, class Out>
struct get_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Out>
{
@@ -308,11 +293,13 @@ struct vtable_adapter<PrimitiveConcept, R(BOOST_PP_ENUM_PARAMS(N, T))>
typedef R (*type)(BOOST_PP_ENUM_PARAMS(N, T));
static R value(BOOST_PP_ENUM_BINARY_PARAMS(N, T, arg))
{
+#if N > 0
typedef typename ::boost::function_traits<
typename ::boost::type_erasure::detail::get_signature<
PrimitiveConcept
>::type
> traits;
+#endif
return PrimitiveConcept::apply(
BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_EXTRACT, ~));
}
@@ -325,11 +312,13 @@ struct vtable_adapter<PrimitiveConcept, ::boost::type_erasure::detail::storage(B
typedef ::boost::type_erasure::detail::storage (*type)(BOOST_PP_ENUM_PARAMS(N, T));
static ::boost::type_erasure::detail::storage value(BOOST_PP_ENUM_BINARY_PARAMS(N, T, arg))
{
+#if N > 0
typedef typename ::boost::function_traits<
typename ::boost::type_erasure::detail::get_signature<
PrimitiveConcept
>::type
> traits;
+#endif
return ::boost::type_erasure::detail::storage(
PrimitiveConcept::apply(
BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_EXTRACT, ~)));
diff --git a/boost/type_erasure/detail/any_base.hpp b/boost/type_erasure/detail/any_base.hpp
index 0fa316c9ff..b7c4f8c050 100644
--- a/boost/type_erasure/detail/any_base.hpp
+++ b/boost/type_erasure/detail/any_base.hpp
@@ -19,7 +19,9 @@ struct any_base
{
typedef void _boost_type_erasure_is_any;
typedef Derived _boost_type_erasure_derived_type;
- void* _boost_type_erasure_deduce_constructor(...) { return 0; }
+ // volatile makes this a worse match than the default constructor
+ // for msvc-14.1, which can get confused otherwise.
+ void* _boost_type_erasure_deduce_constructor(...) const volatile { return 0; }
void* _boost_type_erasure_deduce_assign(...) { return 0; }
};
diff --git a/boost/type_erasure/detail/check_call.hpp b/boost/type_erasure/detail/check_call.hpp
index adf36dbeaa..daa9931146 100644
--- a/boost/type_erasure/detail/check_call.hpp
+++ b/boost/type_erasure/detail/check_call.hpp
@@ -113,10 +113,53 @@ struct check_placeholder_arg :
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
((defined(__GNUC__) && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))) || \
- defined(__MINGW32__) || defined(__MINGW64__))
+ defined(__MINGW32__) || defined(__MINGW64__) || \
+ BOOST_WORKAROUND(BOOST_MSVC, <= 1700))
#define BOOST_TYPE_ERASURE_BROKEN_RVALUE_IS_CONVERTIBLE
#endif
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class P, class Arg>
+using check_placeholder_arg_t =
+ typename ::boost::type_erasure::detail::check_placeholder_arg_impl<
+ P,
+ typename ::boost::type_erasure::detail::qualified_placeholder<Arg>::type
+ >::type;
+
+template<class T, class Arg>
+using check_nonplaceholder_arg_t = typename ::boost::is_convertible<Arg, T>::type;
+
+template<class FormalArg, class ActualArg>
+using check_arg_t =
+ ::boost::type_erasure::detail::eval_if<
+ ::boost::type_erasure::is_placeholder<
+ ::boost::remove_cv_t<
+ ::boost::remove_reference_t<FormalArg>
+ >
+ >::value,
+ ::boost::type_erasure::detail::check_placeholder_arg_t,
+ ::boost::type_erasure::detail::check_nonplaceholder_arg_t,
+ FormalArg,
+ ActualArg
+ >;
+
+// MSVC 14.1 ICE's if we use check_arg_t directly.
+template<class FormalArg, class ActualArg>
+struct check_arg
+{
+ typedef ::boost::type_erasure::detail::check_arg_t<FormalArg, ActualArg> type;
+};
+
+template<class R, class... T, class... U>
+struct check_call<R(T...), void(U...)> {
+ typedef ::boost::mp11::mp_all<
+ typename ::boost::type_erasure::detail::check_arg<T, U>::type...
+ > type;
+};
+
+#else
+
template<class FormalArg, class ActualArg>
struct check_arg
{
@@ -135,10 +178,37 @@ struct check_arg
>::type type;
};
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/check_call.hpp>
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY)
#include BOOST_PP_ITERATE()
+#else
+
+template<class... B>
+struct and_;
+
+template<class T1, class... T>
+struct and_<T1, T...> : boost::mpl::eval_if_c<T1::type::value, and_<T...>, boost::mpl::false_>::type {};
+
+template<class T1>
+struct and_<T1> : T1::type {};
+
+template<>
+struct and_<> : boost::mpl::true_ {};
+
+template<class R, class... T, class... U>
+struct check_call<R(T...), void(U...)> {
+ typedef typename ::boost::type_erasure::detail::and_<
+ ::boost::type_erasure::detail::check_arg<T, U>...
+ >::type type;
+};
+
+#endif
+
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/check_map.hpp b/boost/type_erasure/detail/check_map.hpp
index a51c95deb0..d39b61fba2 100644
--- a/boost/type_erasure/detail/check_map.hpp
+++ b/boost/type_erasure/detail/check_map.hpp
@@ -37,8 +37,18 @@ struct is_deduced< ::boost::type_erasure::deduced<T> > : boost::mpl::true_ {};
// returns true if Map has a key for every non-deduced placeholder in Concept
template<class Concept, class Map>
struct check_map {
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
typedef typename normalize_concept<Concept>::basic basic_components;
-
+
+ typedef typename ::boost::mpl::fold<
+ basic_components,
+ ::boost::mpl::set0<>,
+ ::boost::type_erasure::detail::get_placeholders<
+ ::boost::mpl::_2,
+ ::boost::mpl::_1
+ >
+ >::type placeholders;
+
// Every non-deduced placeholder referenced in this
// map is indirectly deduced.
typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
@@ -51,15 +61,6 @@ struct check_map {
::boost::mpl::second< ::boost::mpl::_2>
>
>::type indirect_deduced_placeholders;
-
- typedef typename ::boost::mpl::fold<
- basic_components,
- ::boost::mpl::set0<>,
- ::boost::type_erasure::detail::get_placeholders<
- ::boost::mpl::_2,
- ::boost::mpl::_1
- >
- >::type placeholders;
typedef typename ::boost::is_same<
typename ::boost::mpl::find_if<
placeholders,
@@ -73,6 +74,35 @@ struct check_map {
>::type,
typename ::boost::mpl::end<placeholders>::type
>::type type;
+
+#else
+ typedef ::boost::type_erasure::detail::get_all_placeholders<
+ ::boost::type_erasure::detail::normalize_concept_t<Concept>
+ > placeholders;
+
+ // Every non-deduced placeholder referenced in this
+ // map is indirectly deduced.
+ typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
+ Concept>::type placeholder_subs;
+ typedef ::boost::mp11::mp_unique<
+ ::boost::mp11::mp_append<
+ ::boost::mp11::mp_transform<
+ ::boost::mp11::mp_first,
+ ::boost::type_erasure::detail::make_mp_list<Map>
+ >,
+ ::boost::mp11::mp_transform<
+ ::boost::mp11::mp_second,
+ ::boost::type_erasure::detail::make_mp_list<placeholder_subs>
+ >
+ >
+ > okay_placeholders;
+ template<class P>
+ using check_placeholder = ::boost::mpl::or_<
+ ::boost::type_erasure::detail::is_deduced<P>,
+ ::boost::mp11::mp_set_contains<okay_placeholders, P>
+ >;
+ typedef ::boost::mp11::mp_all_of<placeholders, check_placeholder> type;
+#endif
};
template<class Concept, class Map>
diff --git a/boost/type_erasure/detail/dynamic_vtable.hpp b/boost/type_erasure/detail/dynamic_vtable.hpp
index 9e014ed61b..959f2f3a32 100644
--- a/boost/type_erasure/detail/dynamic_vtable.hpp
+++ b/boost/type_erasure/detail/dynamic_vtable.hpp
@@ -32,9 +32,15 @@ namespace detail {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
template<class P>
-struct dynamic_binding_impl
-{
+struct dynamic_binding_impl {
const std::type_info * type;
+ dynamic_binding_impl() = default;
+ constexpr dynamic_binding_impl(const std::type_info * t) : type(t) {}
+};
+
+template<class T>
+struct dynamic_binding_element {
+ typedef const std::type_info * type;
};
template<class Table>
@@ -50,12 +56,15 @@ struct append_to_key {
template<class... P>
struct dynamic_vtable : dynamic_binding_impl<P>... {
dynamic_vtable() = default;
- template<class... T>
- constexpr dynamic_vtable(T* ...t) : dynamic_binding_impl<P>{t}... {}
+ constexpr dynamic_vtable(typename dynamic_binding_element<P>::type ...t) : dynamic_binding_impl<P>(t)... {}
template<class F>
typename F::type lookup(F*) const {
key_type key;
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mpl::set0<> >::type placeholders;
+#else
+ typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mp11::mp_list<> >::type placeholders;
+#endif
typedef typename ::boost::mpl::fold<
placeholders,
::boost::mpl::map0<>,
@@ -71,8 +80,13 @@ struct dynamic_vtable : dynamic_binding_impl<P>... {
}
template<class Bindings, class Src>
void convert_from(const Src& src) {
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
*this = dynamic_vtable(
(&src.lookup((::boost::type_erasure::typeid_<typename ::boost::mpl::at<Bindings, P>::type>*)0)())...);
+#else
+ *this = dynamic_vtable(
+ (&src.lookup((::boost::type_erasure::typeid_< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Bindings, P> > >*)0)())...);
+#endif
}
};
diff --git a/boost/type_erasure/detail/extract_concept.hpp b/boost/type_erasure/detail/extract_concept.hpp
index f519045d6c..0b1ce5d2fa 100644
--- a/boost/type_erasure/detail/extract_concept.hpp
+++ b/boost/type_erasure/detail/extract_concept.hpp
@@ -42,6 +42,33 @@ struct combine_concepts<void, T> { typedef T type; };
template<>
struct combine_concepts<void, void> { typedef void type; };
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class T, class U>
+using combine_concepts_t = typename ::boost::type_erasure::detail::combine_concepts<T, U>::type;
+
+template<class T, class U>
+using extract_concept_or_void =
+ ::boost::mp11::mp_eval_if_c<
+ !::boost::type_erasure::is_placeholder<
+ ::boost::remove_cv_t<
+ ::boost::remove_reference_t<T>
+ >
+ >::value,
+ void,
+ ::boost::type_erasure::concept_of_t, U
+ >;
+
+template<class L1, class L2>
+using extract_concept_t =
+ ::boost::mp11::mp_fold<
+ ::boost::mp11::mp_transform< ::boost::type_erasure::detail::extract_concept_or_void, L1, L2>,
+ void,
+ ::boost::type_erasure::detail::combine_concepts_t
+ >;
+
+#else
+
template<class T, class U>
struct maybe_extract_concept
{
@@ -56,7 +83,7 @@ struct maybe_extract_concept
>::type type;
};
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class Args, class... U>
struct extract_concept;
@@ -82,7 +109,6 @@ struct extract_concept<void()>
};
#else
-//#endif
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/extract_concept.hpp>
#define BOOST_PP_ITERATION_LIMITS (1, BOOST_TYPE_ERASURE_MAX_ARITY)
@@ -90,6 +116,8 @@ struct extract_concept<void()>
#endif
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/get_placeholders.hpp b/boost/type_erasure/detail/get_placeholders.hpp
index cdee16fc03..a17d2d445c 100644
--- a/boost/type_erasure/detail/get_placeholders.hpp
+++ b/boost/type_erasure/detail/get_placeholders.hpp
@@ -21,6 +21,7 @@
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
#include <boost/type_erasure/config.hpp>
#include <boost/type_erasure/is_placeholder.hpp>
@@ -28,6 +29,87 @@ namespace boost {
namespace type_erasure {
namespace detail {
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class T>
+struct get_placeholders_in_argument_impl
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::eval_if<
+ ::boost::type_erasure::is_placeholder<T>::value,
+ ::boost::mp11::mp_set_push_back,
+ ::boost::type_erasure::detail::first,
+ Out, T
+ >;
+};
+
+template<class T>
+struct get_placeholders_in_argument_impl<T&>
+{
+ template<class Out>
+ using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl<T>::template apply<Out>;
+};
+
+template<class T>
+struct get_placeholders_in_argument_impl<T&&>
+{
+ template<class Out>
+ using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl<T>::template apply<Out>;
+};
+
+template<class T>
+struct get_placeholders_in_argument_impl<const T>
+{
+ template<class Out>
+ using apply = typename ::boost::type_erasure::detail::get_placeholders_in_argument_impl<T>::template apply<Out>;
+};
+
+template<class Out, class T>
+using get_placeholders_f = typename get_placeholders_in_argument_impl<T>::template apply<Out>;
+
+template<class Out, class... T>
+using get_placeholders_impl =
+ ::boost::mp11::mp_fold<
+ ::boost::mp11::mp_list<T...>,
+ Out,
+ ::boost::type_erasure::detail::get_placeholders_f
+ >;
+
+template<class R, class... T>
+struct get_placeholders_in_argument_impl<R(T...)>
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::get_placeholders_impl<Out, R, T...>;
+};
+
+template<class R, class C, class... T>
+struct get_placeholders_in_argument_impl<R (C::*)(T...)>
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::get_placeholders_impl<Out, R, C, T...>;
+};
+
+template<class R, class C, class... T>
+struct get_placeholders_in_argument_impl<R (C::*)(T...) const>
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::get_placeholders_impl<Out, R, C, T...>;
+};
+
+template<class T, class Out>
+struct get_placeholders;
+
+template<template<class...> class F, class... T, class Out>
+struct get_placeholders<F<T...>, Out>
+{
+ using type = ::boost::type_erasure::detail::get_placeholders_impl<Out, T...>;
+};
+
+template<class T, class Out>
+using get_placeholders_t = typename ::boost::type_erasure::detail::get_placeholders<T, Out>::type;
+
+#else
+
template<class T, class Out>
struct get_placeholders_in_argument
{
@@ -88,11 +170,19 @@ struct get_placeholders<T<U...>, Out>
template<class R, class... T, class Out>
struct get_placeholders_in_argument<R(T...), Out>
{
- typedef typename ::boost::type_erasure::detail::get_placeholders_in_argument<
- R,
- Out
- >::type type0;
- typedef typename get_placeholders_impl<type0, T...>::type type;
+ typedef typename get_placeholders_impl<Out, R, T...>::type type;
+};
+
+template<class R, class C, class... T, class Out>
+struct get_placeholders_in_argument<R (C::*)(T...), Out>
+{
+ typedef typename get_placeholders_impl<Out, R, C, T...>::type type;
+};
+
+template<class R, class C, class... T, class Out>
+struct get_placeholders_in_argument<R (C::*)(T...) const, Out>
+{
+ typedef typename get_placeholders_impl<Out, R, C, T...>::type type;
};
#else
@@ -103,6 +193,8 @@ struct get_placeholders_in_argument<R(T...), Out>
#endif
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/instantiate.hpp b/boost/type_erasure/detail/instantiate.hpp
index 74f3d27f83..742aa02a9b 100644
--- a/boost/type_erasure/detail/instantiate.hpp
+++ b/boost/type_erasure/detail/instantiate.hpp
@@ -28,6 +28,62 @@ namespace boost {
namespace type_erasure {
namespace detail {
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class L>
+struct make_instantiate_concept_impl;
+
+template<class T, T t>
+struct instantiate_concept;
+
+template<class T>
+using instantiate_concept_impl = instantiate_concept<decltype(&T::apply), &T::apply>;
+
+template<class... T>
+struct make_instantiate_concept_impl< ::boost::mp11::mp_list<T...> >
+{
+ template<template<class> class F>
+ using apply = void(F<T>...);
+};
+
+template<class Map>
+struct instantiate_concept_rebind_f
+{
+ template<class T>
+ using apply =
+ typename ::boost::type_erasure::detail::rebind_placeholders<
+ T,
+ Map
+ >::type;
+};
+
+template<class Concept, class Map>
+using make_instantiate_concept =
+ ::boost::type_erasure::detail::make_instantiate_concept_impl<
+ ::boost::mp11::mp_transform<
+ ::boost::type_erasure::detail::instantiate_concept_rebind_f<
+ typename ::boost::type_erasure::detail::add_deductions<
+ ::boost::type_erasure::detail::make_mp_list<Map>,
+ typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
+ Concept
+ >::type
+ >::type
+ >::template apply,
+ ::boost::type_erasure::detail::normalize_concept_t<Concept>
+ >
+ >;
+
+#define BOOST_TYPE_ERASURE_INSTANTIATE(Concept, Map) \
+ ((void)(typename ::boost::type_erasure::detail::make_instantiate_concept<Concept, Map> \
+ ::template apply< ::boost::type_erasure::detail::instantiate_concept_impl>*)0)
+
+#define BOOST_TYPE_ERASURE_INSTANTIATE1(Concept, P0, T0) \
+ ((void)(typename ::boost::type_erasure::detail::make_instantiate_concept< \
+ Concept, ::boost::mpl::map1< ::boost::mpl::pair<P0, T0> > > \
+ ::template apply< ::boost::type_erasure::detail::instantiate_concept_impl>*)0)
+
+#else
+
template<int N>
struct make_instantiate_concept_impl;
@@ -56,6 +112,8 @@ struct make_instantiate_concept {
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_FUNCTIONS)
#include BOOST_PP_ITERATE()
+#endif
+
}
}
}
@@ -72,6 +130,7 @@ struct make_instantiate_concept {
struct BOOST_PP_CAT(instantiate_concept, N) {
template<class Concept, class Map>
static void apply(Concept *, Map *) {
+#if N > 0
typedef typename ::boost::type_erasure::detail::normalize_concept<
Concept>::type normalized;
typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
@@ -88,6 +147,7 @@ struct BOOST_PP_CAT(instantiate_concept, N) {
>::type
>
>::type concept_sequence;
+#endif
BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_INSTANTIATE_IMPL, concept_sequence)
}
};
diff --git a/boost/type_erasure/detail/member11.hpp b/boost/type_erasure/detail/member11.hpp
new file mode 100644
index 0000000000..7bc8eee6a9
--- /dev/null
+++ b/boost/type_erasure/detail/member11.hpp
@@ -0,0 +1,214 @@
+// Boost.TypeErasure library
+//
+// Copyright 2018 Steven Watanabe
+//
+// Distributed under the Boost Software License Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// $Id$
+
+#ifndef BOOST_TYPE_ERASURE_DETAIL_MEMBER11_HPP_INCLUDED
+#define BOOST_TYPE_ERASURE_DETAIL_MEMBER11_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
+ !defined(BOOST_NO_CXX11_DECLTYPE) && \
+ !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/punctuation/is_begin_parens.hpp>
+#include <boost/vmd/is_empty.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_erasure/detail/const.hpp>
+#include <boost/type_erasure/detail/macro.hpp>
+#include <boost/type_erasure/rebind_any.hpp>
+#include <boost/type_erasure/param.hpp>
+#include <boost/type_erasure/is_placeholder.hpp>
+#include <boost/type_erasure/call.hpp>
+
+namespace boost {
+namespace type_erasure {
+namespace detail {
+
+template<class P, template<class ...> class interface, class Sig, class Concept, class Base, class ID>
+using choose_member_interface = typename ::boost::mpl::if_c< ::boost::is_reference<P>::value,
+ typename ::boost::mpl::if_c< ::boost::type_erasure::detail::is_non_const_ref<P>::value,
+ interface<Sig, Concept, Base, const ID>,
+ Base
+ >::type,
+ interface<Sig, Concept, Base, ID>
+>::type;
+
+
+struct dummy {};
+
+template<class Sig>
+struct choose_member_impl;
+
+template<class R, class C, class... T>
+struct choose_member_impl<R (C::*)(T...) const>
+{
+ template<class P, template<class> class M, template<class,class> class S>
+ using apply = ::boost::mpl::vector1<S<R(T...), const P> >;
+};
+
+template<class R, class C, class... T>
+struct choose_member_impl<R (C::*)(T...)>
+{
+ template<class P, template<class> class M, template<class,class> class S>
+ using apply = M<R(P&, T...)>;
+};
+
+template<class Sig, class P, template<class> class M, template<class, class> class Self>
+using choose_member_impl_t =
+ typename ::boost::type_erasure::detail::choose_member_impl<
+ Sig (::boost::type_erasure::detail::dummy::*)
+ >::template apply<P, M, Self>;
+
+template<class Sig, class T, class ID>
+struct member_interface_chooser
+{
+ template<class Base, template<class, class> class C, template<class...> class M>
+ using apply = Base;
+};
+
+template<class R, class T, class... A>
+struct member_interface_chooser<R(A...), T, T>
+{
+ template<class Base, template<class, class> class C, template<class...> class M>
+ using apply = ::boost::type_erasure::detail::choose_member_interface<
+ ::boost::type_erasure::placeholder_of_t<Base>,
+ M,
+ R(A...), C<R(A...), T>, Base, T>;
+};
+
+template<class R, class T, class... A>
+struct member_interface_chooser<R(A...), const T, T>
+{
+ template<class Base, template<class, class> class C, template<class...> class M>
+ using apply = M<R(A...), C<R(A...), const T>, Base, const T>;
+};
+
+template<class Sig, class T, template<class, class> class C, template<class...> class M>
+struct member_choose_interface
+{
+ template<class Concept, class Base, class ID>
+ using apply = typename ::boost::type_erasure::detail::member_interface_chooser<Sig, T, ID>::template apply<Base, C, M>;
+};
+
+}
+}
+}
+
+#define BOOST_TYPE_ERASURE_MEMBER_I(concept_name, function_name) \
+template<class Sig, class T = ::boost::type_erasure::_self> \
+struct concept_name; \
+ \
+namespace boost_type_erasure_impl { \
+ \
+template<class Sig, class T> \
+using concept_name ## self = concept_name<Sig, T>; \
+ \
+template<class Sig, class Concept, class Base, class ID, class Enable = void>\
+struct concept_name ## _member_interface; \
+ \
+template<class R, class... A, class Concept, class Base, class ID, class V> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, ID, V> : Base\
+{ \
+ typedef void _boost_type_erasure_has_member ## function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class R, class... A, class Concept, class Base, class ID> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, ID, \
+ typename Base::_boost_type_erasure_has_member ## function_name> : Base \
+{ \
+ using Base::function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a)\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class R, class... A, class Concept, class Base, class ID, class V> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, V> : Base\
+{ \
+ typedef void _boost_type_erasure_has_member ## function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class R, class... A, class Concept, class Base, class ID> \
+struct concept_name ## _member_interface<R(A...), Concept, Base, const ID, \
+ typename Base::_boost_type_erasure_has_member ## function_name> : Base \
+{ \
+ using Base::function_name; \
+ ::boost::type_erasure::rebind_any_t<Base, R> function_name(::boost::type_erasure::as_param_t<Base, A>... a) const\
+ { return ::boost::type_erasure::call(Concept(), *this, std::forward<A>(a)...); }\
+}; \
+ \
+template<class Sig> \
+struct concept_name ## member; \
+ \
+template<class R, class T0, class... T> \
+struct concept_name ## member<R(T0, T...)> { \
+ static R apply(T0 t0, T... t) \
+ { return t0.function_name(std::forward<T>(t)...); } \
+}; \
+ \
+template<class T0, class... T> \
+struct concept_name ## member<void(T0, T...)> { \
+ static void apply(T0 t0, T... t) \
+ { t0.function_name(std::forward<T>(t)...); } \
+}; \
+ \
+} \
+ \
+template<class Sig, class T> \
+struct concept_name : \
+ ::boost::type_erasure::detail::choose_member_impl_t<Sig, T, \
+ boost_type_erasure_impl::concept_name##member, \
+ boost_type_erasure_impl::concept_name##self \
+ > \
+{}; \
+ \
+template<class Sig, class T> \
+::boost::type_erasure::detail::member_choose_interface<Sig, T, concept_name,\
+ boost_type_erasure_impl::concept_name ## _member_interface> \
+boost_type_erasure_find_interface(concept_name<Sig, T>);
+
+#define BOOST_TYPE_ERASURE_MEMBER_SIMPLE(name, ...) \
+ BOOST_TYPE_ERASURE_MEMBER_I(has_ ## name, name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_NS_I(concept_name, name) \
+ BOOST_TYPE_ERASURE_MEMBER_I(concept_name, name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_NS(concept_name, name) \
+ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(concept_name) \
+ BOOST_TYPE_ERASURE_MEMBER_NS_I(BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(concept_name)), concept_name), name) \
+ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(concept_name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_NAMED(concept_name, name, ...) \
+ BOOST_PP_IF(BOOST_PP_IS_BEGIN_PARENS(concept_name), \
+ BOOST_TYPE_ERASURE_MEMBER_NS, \
+ BOOST_TYPE_ERASURE_MEMBER_I) \
+ (concept_name, name)
+
+#define BOOST_TYPE_ERASURE_MEMBER_CAT(x, y) x y
+
+#define BOOST_TYPE_ERASURE_MEMBER(name, ...) \
+ BOOST_TYPE_ERASURE_MEMBER_CAT( \
+ BOOST_PP_IF(BOOST_VMD_IS_EMPTY(__VA_ARGS__), \
+ BOOST_TYPE_ERASURE_MEMBER_SIMPLE, \
+ BOOST_TYPE_ERASURE_MEMBER_NAMED), \
+ (name, __VA_ARGS__))
+
+#endif
+
+#endif
diff --git a/boost/type_erasure/detail/meta.hpp b/boost/type_erasure/detail/meta.hpp
new file mode 100644
index 0000000000..96e786fde6
--- /dev/null
+++ b/boost/type_erasure/detail/meta.hpp
@@ -0,0 +1,89 @@
+// Boost.TypeErasure library
+//
+// Copyright 2018 Steven Watanabe
+//
+// Distributed under the Boost Software License Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// $Id$
+
+#ifndef BOOST_TYPE_ERASURE_DETAIL_META_HPP_INCLUDED
+#define BOOST_TYPE_ERASURE_DETAIL_META_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
+ !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && \
+ /* MSVC 14.0 breaks down in the template alias quagmire. */ \
+ !BOOST_WORKAROUND(BOOST_MSVC, <= 1900)
+
+#define BOOST_TYPE_ERASURE_USE_MP11
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/map.hpp>
+#include <boost/mp11/set.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+#include <boost/mp11/mpl.hpp>
+
+namespace boost {
+namespace type_erasure {
+namespace detail {
+
+struct mp11_list_inserter
+{
+ template<class L, class T>
+ using apply = ::boost::mpl::identity< ::boost::mp11::mp_push_back<L, T> >;
+};
+
+template<class T>
+struct make_mp_list_impl
+{
+ typedef typename ::boost::mpl::fold<
+ T,
+ ::boost::mp11::mp_list<>,
+ ::boost::type_erasure::detail::mp11_list_inserter
+ >::type type;
+};
+
+template<class... T>
+struct make_mp_list_impl< ::boost::mp11::mp_list<T...> >
+{
+ typedef ::boost::mp11::mp_list<T...> type;
+};
+
+template<class T>
+using make_mp_list = typename make_mp_list_impl<T>::type;
+
+template<bool>
+struct eval_if_impl;
+
+template<>
+struct eval_if_impl<true>
+{
+ template<template<class...> class T, template<class...> class F, class... A>
+ using apply = T<A...>;
+};
+
+template<>
+struct eval_if_impl<false>
+{
+ template<template<class...> class T, template<class...> class F, class... A>
+ using apply = F<A...>;
+};
+
+template<bool B, template<class...> class T, template<class...> class F, class... A>
+using eval_if = typename ::boost::type_erasure::detail::eval_if_impl<B>::template apply<T, F, A...>;
+
+template<class T0, class...>
+using first = T0;
+
+}
+}
+}
+
+#endif
+
+#endif
diff --git a/boost/type_erasure/detail/normalize.hpp b/boost/type_erasure/detail/normalize.hpp
index a6849a6cd9..02c232a612 100644
--- a/boost/type_erasure/detail/normalize.hpp
+++ b/boost/type_erasure/detail/normalize.hpp
@@ -30,6 +30,7 @@
#include <boost/type_erasure/detail/get_placeholders.hpp>
#include <boost/type_erasure/detail/rebind_placeholders.hpp>
#include <boost/type_erasure/detail/normalize_deduced.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
#include <boost/type_erasure/relaxed.hpp>
#include <boost/type_erasure/builtin.hpp>
@@ -43,7 +44,6 @@ template<class T, class U>
struct same_type;
namespace detail {
-
struct substitution_map_tag {};
// a wrapper around an mpl::map that
@@ -87,20 +87,6 @@ struct has_key_impl< ::boost::type_erasure::detail::substitution_map_tag>
namespace type_erasure {
namespace detail {
-// given a partial substitution map from same_type,
-// resolves a placeholder as far as possible.
-template<class M, class T>
-struct resolve_same_type
-{
- typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
- ::boost::type_erasure::detail::resolve_same_type<
- M,
- typename ::boost::mpl::at<M, T>::type
- >,
- ::boost::mpl::identity<T>
- >::type type;
-};
-
// Given the arguments to same_type, determines
// which should be the key and which should be
// the value in the substitution map.
@@ -135,6 +121,22 @@ struct select_pair<
> type;
};
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
+
+// given a partial substitution map from same_type,
+// resolves a placeholder as far as possible.
+template<class M, class T>
+struct resolve_same_type
+{
+ typedef typename ::boost::mpl::eval_if< ::boost::mpl::has_key<M, T>,
+ ::boost::type_erasure::detail::resolve_same_type<
+ M,
+ typename ::boost::mpl::at<M, T>::type
+ >,
+ ::boost::mpl::identity<T>
+ >::type type;
+};
+
// M is a map of placeholder substitutions
template<class M, class T>
struct normalize_placeholder
@@ -377,20 +379,422 @@ struct collect_concepts
Concept,
::boost::type_erasure::detail::substitution_map<Map>
>::type transformed;
+ typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence<Concept>,
+ ::boost::mpl::fold<Concept, Out, collect_concepts< ::boost::mpl::_2, Map, ::boost::mpl::_1> >,
+ ::boost::mpl::identity<Out>
+ >::type type1;
typedef typename ::boost::mpl::eval_if<
::boost::is_same<transformed, void>,
- ::boost::mpl::identity<Out>,
+ ::boost::mpl::identity<type1>,
::boost::mpl::insert<
- Out,
+ type1,
transformed
>
- >::type type1;
- typedef typename ::boost::mpl::eval_if< ::boost::mpl::is_sequence<Concept>,
- ::boost::mpl::fold<Concept, type1, collect_concepts< ::boost::mpl::_2, Map, ::boost::mpl::_1> >,
- ::boost::mpl::identity<type1>
>::type type;
};
+#else
+
+template<bool>
+struct resolve_same_type_impl;
+
+template<class M, class T>
+using resolve_same_type_t =
+ typename ::boost::type_erasure::detail::resolve_same_type_impl<
+ (::boost::mp11::mp_map_contains<M, T>::value)
+ >::template apply<M, T>;
+
+template<>
+struct resolve_same_type_impl<true>
+{
+ template<class M, class T>
+ using apply = ::boost::type_erasure::detail::resolve_same_type_t<
+ M,
+ ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<M, T> >
+ >;
+};
+
+template<>
+struct resolve_same_type_impl<false>
+{
+ template<class M, class T>
+ using apply = T;
+};
+
+// given a partial substitution map from same_type,
+// resolves a placeholder as far as possible.
+template<class M, class T>
+using resolve_same_type = ::boost::mpl::identity< ::boost::type_erasure::detail::resolve_same_type_t<M, T> >;
+
+
+// M is a map of placeholder substitutions
+
+template<bool>
+struct normalize_placeholder_impl;
+
+template<class M, class T>
+using normalize_placeholder_t =
+ typename ::boost::type_erasure::detail::normalize_placeholder_impl<
+ ::boost::mp11::mp_map_contains<M, T>::value
+ >::template apply<M, T>;
+
+template<>
+struct normalize_placeholder_impl<true>
+{
+ template<class M, class T>
+ using apply = ::boost::type_erasure::detail::normalize_placeholder_t<
+ M,
+ typename ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<M, T> >
+ >;
+};
+
+template<class T>
+struct normalize_deduced_impl
+{
+ template<class Map>
+ using apply = T;
+};
+
+template<template<class...> class F, class... T>
+struct normalize_deduced_impl< ::boost::type_erasure::deduced<F<T...> > >
+{
+ template<class Map>
+ using apply = typename ::boost::type_erasure::deduced<F<normalize_placeholder_t<Map, T>...> >::type;
+};
+
+template<>
+struct normalize_placeholder_impl<false>
+{
+ template<class M, class T>
+ using apply = typename ::boost::type_erasure::detail::normalize_deduced_impl<T>::template apply<M>;
+};
+
+template<class Map, class T>
+using normalize_placeholder = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_placeholder_t<Map, T> >;
+
+// Takes a mpl::map of placeholder substitutions and
+// fully resolves it. i.e. a -> b, b -> c, becomes
+// a -> c, b -> c. Also resolves deduced placeholders
+// whose arguments are all resolved.
+template<class M>
+struct create_placeholder_map
+{
+ template<class P>
+ using transform_one = ::boost::mpl::pair<
+ typename ::boost::mpl::first<P>::type,
+ ::boost::type_erasure::detail::normalize_placeholder_t<
+ M,
+ typename ::boost::mpl::second<P>::type
+ >
+ >;
+ typedef ::boost::mp11::mp_transform<
+ transform_one,
+ M
+ > type;
+};
+
+template<class M>
+using create_placeholder_map_t = typename ::boost::type_erasure::detail::create_placeholder_map<M>::type;
+
+template<class Bindings, class P, class Out, class Sub>
+struct convert_deduced
+{
+ typedef ::boost::type_erasure::detail::rebind_placeholders_in_argument_t<
+ typename P::first,
+ Bindings
+ > result1;
+ typedef ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Sub, result1> > result;
+ typedef ::boost::mp11::mp_map_insert<Out, ::boost::mpl::pair<typename P::second, result> > type;
+ BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<type, typename P::second> >, result>));
+};
+
+template<class Bindings, class Sub>
+struct convert_deduced_f
+{
+ template<class Out, class P>
+ using apply = typename ::boost::type_erasure::detail::convert_deduced<Bindings, P, Out, Sub>::type;
+};
+
+template<class Bindings, class M, class Sub>
+using convert_deductions_t =
+ ::boost::mp11::mp_fold<
+ M,
+ ::boost::type_erasure::detail::make_mp_list<Bindings>,
+ ::boost::type_erasure::detail::convert_deduced_f<Bindings, Sub>::template apply
+ >;
+
+template<class Bindings, class M, class Sub>
+using convert_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::convert_deductions_t<Bindings, M, Sub> >;
+
+template<class Bindings, class P, class Out>
+struct add_deduced
+{
+ typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
+ typename P::first,
+ Bindings
+ >::type result;
+ typedef ::boost::mp11::mp_map_insert<Out, ::boost::mpl::pair<typename P::second, result> > type;
+ BOOST_MPL_ASSERT((boost::is_same< ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<type, typename P::second> >, result>));
+};
+
+template<class Bindings>
+struct add_deduced_f
+{
+ template<class Out, class P>
+ using apply = typename ::boost::type_erasure::detail::add_deduced<Bindings, P, Out>::type;
+};
+
+template<class Bindings, class M>
+using add_deductions_t =
+ ::boost::mp11::mp_fold<
+ M,
+ ::boost::type_erasure::detail::make_mp_list<Bindings>,
+ ::boost::type_erasure::detail::add_deduced_f<
+ ::boost::type_erasure::detail::make_mp_list<Bindings>
+ >::template apply
+ >;
+
+template<class Bindings, class M>
+using add_deductions = ::boost::mpl::identity< ::boost::type_erasure::detail::add_deductions_t<Bindings, M> >;
+
+// Fold Op for normalize_concept_impl
+template<class T>
+struct insert_concept_impl
+{
+ template<class Out>
+ using apply =
+ ::boost::mpl::pair<
+ ::boost::mp11::mp_set_push_back<typename Out::first, T>,
+ typename Out::second
+ >;
+};
+
+template<class Map, class T>
+using mpl_insert = typename ::boost::mpl::insert<Map, T>::type;
+
+template<class T1, class T2, class Out>
+using insert_concept_same_type =
+ ::boost::mpl::pair<
+ typename Out::first,
+ typename ::boost::type_erasure::detail::eval_if<
+ ::boost::is_same<T1, T2>::value,
+ ::boost::type_erasure::detail::first,
+ ::boost::mp11::mp_map_insert, // FIXME: is this supposed to be a replace?
+ typename Out::second,
+ typename ::boost::type_erasure::detail::select_pair<
+ T1,
+ T2
+ >::type
+ >
+ >;
+
+template<class T, class U>
+struct insert_concept_impl< ::boost::type_erasure::same_type<T, U> >
+{
+ template<class Out>
+ using apply = ::boost::type_erasure::detail::insert_concept_same_type<
+ ::boost::type_erasure::detail::resolve_same_type_t<
+ typename Out::second,
+ T
+ >,
+ ::boost::type_erasure::detail::resolve_same_type_t<
+ typename Out::second,
+ U
+ >,
+ Out
+ >;
+};
+
+template<bool>
+struct normalize_concept_impl_test;
+
+template<class Out, class Concept>
+using normalize_concept_impl_f =
+ typename ::boost::type_erasure::detail::normalize_concept_impl_test<
+ ::boost::mpl::is_sequence<Concept>::value
+ >::template apply<Out, Concept>;
+
+template<>
+struct normalize_concept_impl_test<true>
+{
+ template<class Out, class Concept>
+ using apply =
+ ::boost::mp11::mp_fold<
+ ::boost::type_erasure::detail::make_mp_list<Concept>,
+ Out,
+ ::boost::type_erasure::detail::normalize_concept_impl_f
+ >;
+};
+
+template<>
+struct normalize_concept_impl_test<false>
+{
+ template<class Out, class Concept>
+ using apply = typename ::boost::type_erasure::detail::insert_concept_impl<Concept>::template apply<Out>;
+};
+
+template<class Concept>
+using normalize_concept_impl_t =
+ ::boost::type_erasure::detail::normalize_concept_impl_f<
+ ::boost::mpl::pair< ::boost::mp11::mp_list<>, ::boost::mp11::mp_list<> >,
+ Concept
+ >;
+
+template<class Concept>
+using normalize_concept_impl = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_impl_t<Concept> >;
+
+template<class S, class T>
+using get_all_placeholders_impl = typename ::boost::type_erasure::detail::get_placeholders<T, S>::type;
+
+template<class Seq>
+using get_all_placeholders =
+ ::boost::mp11::mp_fold<
+ Seq,
+ ::boost::mp11::mp_list<>,
+ ::boost::type_erasure::detail::get_all_placeholders_impl
+ >;
+
+template<class T>
+using make_identity_pair = ::boost::mpl::pair<T, T>;
+
+template<class Concept>
+using make_identity_placeholder_map =
+ ::boost::mp11::mp_transform<
+ ::boost::type_erasure::detail::make_identity_pair,
+ ::boost::type_erasure::detail::get_all_placeholders<
+ typename normalize_concept_impl_t<Concept>::first
+ >
+ >;
+
+template<class S, class T>
+using append_type_info = ::boost::mp11::mp_set_push_back<
+ S,
+ ::boost::type_erasure::typeid_<T>
+>;
+
+template<class Seq>
+using add_typeinfo_t =
+ ::boost::mp11::mp_fold<
+ get_all_placeholders<Seq>,
+ Seq,
+ ::boost::type_erasure::detail::append_type_info
+ >;
+
+// Seq should be a flattened mp_list sequence of leaf concepts.
+// adds typeid_<P> for every placeholder used.
+template<class Seq>
+using add_typeinfo = ::boost::mpl::identity<add_typeinfo_t<Seq> >;
+
+template<class Substitutions>
+struct normalize_concept_substitute_f
+{
+ template<class Set, class Concept>
+ using apply = ::boost::mp11::mp_set_push_back<Set,
+ typename ::boost::type_erasure::detail::rebind_placeholders<
+ Concept,
+ Substitutions
+ >::type
+ >;
+};
+
+template<class Concept, class Pair>
+using normalize_concept_adjustments =
+ ::boost::type_erasure::detail::eval_if<
+ ::boost::type_erasure::is_relaxed<Concept>::value,
+ ::boost::type_erasure::detail::add_typeinfo_t,
+ ::boost::type_erasure::detail::first,
+ ::boost::mp11::mp_fold<
+ typename Pair::first,
+ ::boost::mp11::mp_list<>,
+ ::boost::type_erasure::detail::normalize_concept_substitute_f<
+ ::boost::type_erasure::detail::create_placeholder_map_t<
+ typename Pair::second
+ >
+ >::template apply
+ >
+ >;
+
+template<class Concept>
+using get_placeholder_normalization_map_t =
+ ::boost::type_erasure::detail::create_placeholder_map_t<
+ typename normalize_concept_impl_t<Concept>::second
+ >;
+
+template<class Concept>
+using get_placeholder_normalization_map =
+ ::boost::type_erasure::detail::create_placeholder_map<
+ typename normalize_concept_impl_t<Concept>::second
+ >;
+
+// Flattens a Concept to an mpl::vector of primitive
+// concepts. Resolves same_type and deduced placeholders.
+template<class Concept>
+using normalize_concept_t =
+ ::boost::type_erasure::detail::normalize_concept_adjustments<
+ Concept,
+ boost::type_erasure::detail::normalize_concept_impl_t<Concept>
+ >;
+
+template<class Concept>
+using normalize_concept = ::boost::mpl::identity< ::boost::type_erasure::detail::normalize_concept_t<Concept> >;
+
+template<class Map>
+struct collect_concepts_f;
+
+template<class Out, class Concept, class Map>
+using collect_concepts_recursive = ::boost::mp11::mp_fold<
+ ::boost::type_erasure::detail::make_mp_list<Concept>,
+ Out,
+ ::boost::type_erasure::detail::collect_concepts_f<Map>::template apply
+>;
+
+template<class Concept, class Map, class Out, class Transformed>
+using collect_concepts_impl =
+ ::boost::type_erasure::detail::eval_if< ::boost::is_same<Transformed, void>::value,
+ ::boost::type_erasure::detail::first,
+ ::boost::mp11::mp_set_push_front,
+ ::boost::type_erasure::detail::eval_if< ::boost::mpl::is_sequence<Concept>::value,
+ ::boost::type_erasure::detail::collect_concepts_recursive,
+ ::boost::type_erasure::detail::first,
+ Out,
+ Concept,
+ Map
+ >,
+ Transformed
+ >;
+
+template<class Concept,
+ class Map = ::boost::type_erasure::detail::create_placeholder_map_t<
+ typename ::boost::type_erasure::detail::normalize_concept_impl_t<
+ Concept
+ >::second
+ >,
+ class Out = ::boost::mp11::mp_list<>
+>
+using collect_concepts_t =
+ collect_concepts_impl<Concept, Map, Out,
+ typename ::boost::type_erasure::detail::rebind_placeholders<
+ Concept,
+ Map
+ >::type
+ >;
+
+template<class Map>
+struct collect_concepts_f
+{
+ template<class Out, class Concept>
+ using apply = ::boost::type_erasure::detail::collect_concepts_t<Concept, Map, Out>;
+};
+
+// Returns an MPL sequence containing all the concepts
+// in Concept. If Concept is considered as a DAG,
+// the result will be sorted topologically.
+template<class Concept>
+using collect_concepts = ::boost::mpl::identity<
+ ::boost::type_erasure::detail::collect_concepts_t<Concept> >;
+
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/normalize_deduced.hpp b/boost/type_erasure/detail/normalize_deduced.hpp
index 83d0d3b25b..dcf3fd3625 100644
--- a/boost/type_erasure/detail/normalize_deduced.hpp
+++ b/boost/type_erasure/detail/normalize_deduced.hpp
@@ -16,6 +16,9 @@
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
+
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
namespace boost {
namespace type_erasure {
@@ -36,6 +39,8 @@ struct normalize_placeholder;
#endif
+#endif
+
#else
#define N BOOST_PP_ITERATION()
diff --git a/boost/type_erasure/detail/null.hpp b/boost/type_erasure/detail/null.hpp
index ef977f4254..e0c3173704 100644
--- a/boost/type_erasure/detail/null.hpp
+++ b/boost/type_erasure/detail/null.hpp
@@ -13,6 +13,7 @@
#ifndef BOOST_TYPE_ERASURE_DETAIL_NULL_HPP_INCLUDED
#define BOOST_TYPE_ERASURE_DETAIL_NULL_HPP_INCLUDED
+#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
@@ -34,10 +35,23 @@ struct get_null_vtable_entry {
typename ::boost::remove_pointer<typename Concept::type>::type> type;
};
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/null.hpp>
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_ARITY)
#include BOOST_PP_ITERATE()
+#else
+
+template<class R, class... T>
+struct null_throw<R(T...)> {
+ static R value(T...) {
+ BOOST_THROW_EXCEPTION(::boost::type_erasure::bad_function_call());
+ }
+};
+
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/rebind_placeholders.hpp b/boost/type_erasure/detail/rebind_placeholders.hpp
index d93d429c5d..0d0ef7c8e4 100644
--- a/boost/type_erasure/detail/rebind_placeholders.hpp
+++ b/boost/type_erasure/detail/rebind_placeholders.hpp
@@ -26,6 +26,7 @@
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/type_erasure/config.hpp>
+#include <boost/type_erasure/detail/meta.hpp>
#include <boost/type_erasure/is_placeholder.hpp>
namespace boost {
@@ -48,6 +49,132 @@ struct identity
typedef T type;
};
+template<class PrimitiveConcept, class Sig>
+struct vtable_adapter;
+
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class T, class Bindings>
+using rebind_placeholders_t = typename rebind_placeholders<T, Bindings>::type;
+
+template<class T, class Bindings>
+using rebind_one_placeholder = ::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Bindings, T> >;
+
+template<class T>
+struct rebind_placeholders_in_argument_impl
+{
+ template<class Bindings>
+ using apply = ::boost::type_erasure::detail::eval_if<
+ ::boost::mp11::mp_map_contains<Bindings, T>::value,
+ ::boost::type_erasure::detail::rebind_one_placeholder,
+ ::boost::type_erasure::detail::first,
+ T,
+ Bindings
+ >;
+};
+
+template<class T, class Bindings>
+using rebind_placeholders_in_argument_t = typename ::boost::type_erasure::detail::rebind_placeholders_in_argument_impl<T>::template apply<Bindings>;
+
+template<class T, class Bindings>
+using rebind_placeholders_in_argument = ::boost::mpl::identity< ::boost::type_erasure::detail::rebind_placeholders_in_argument_t<T, Bindings> >;
+
+template<class T>
+struct rebind_placeholders_in_argument_impl<T&>
+{
+ template<class Bindings>
+ using apply = rebind_placeholders_in_argument_t<T, Bindings>&;
+};
+
+template<class T>
+struct rebind_placeholders_in_argument_impl<T&&>
+{
+ template<class Bindings>
+ using apply = rebind_placeholders_in_argument_t<T, Bindings>&&;
+};
+
+template<class T>
+struct rebind_placeholders_in_argument_impl<const T>
+{
+ template<class Bindings>
+ using apply = rebind_placeholders_in_argument_t<T, Bindings> const;
+};
+
+template<class F, class Bindings>
+using rebind_placeholders_in_deduced =
+ typename ::boost::type_erasure::deduced<
+ ::boost::type_erasure::detail::rebind_placeholders_t<F, Bindings>
+ >::type;
+
+template<class F, class Bindings>
+using rebind_deduced_placeholder =
+ ::boost::mp11::mp_second<
+ ::boost::mp11::mp_map_find<Bindings, ::boost::type_erasure::deduced<F> >
+ >;
+
+template<class F>
+struct rebind_placeholders_in_argument_impl<
+ ::boost::type_erasure::deduced<F>
+>
+{
+ template<class Bindings>
+ using apply = ::boost::type_erasure::detail::eval_if<
+ ::boost::mp11::mp_map_contains<Bindings, ::boost::type_erasure::deduced<F> >::value,
+ ::boost::type_erasure::detail::rebind_deduced_placeholder,
+ ::boost::type_erasure::detail::rebind_placeholders_in_deduced,
+ F,
+ Bindings
+ >;
+};
+
+template<class R, class... T>
+struct rebind_placeholders_in_argument_impl<R(T...)>
+{
+ template<class Bindings>
+ using apply =
+ rebind_placeholders_in_argument_t<R, Bindings>
+ (rebind_placeholders_in_argument_t<T, Bindings>...);
+};
+
+template<class R, class C, class... T>
+struct rebind_placeholders_in_argument_impl<R (C::*)(T...)>
+{
+ template<class Bindings>
+ using apply =
+ rebind_placeholders_in_argument_t<R, Bindings>
+ (rebind_placeholders_in_argument_t<C, Bindings>::*)
+ (rebind_placeholders_in_argument_t<T, Bindings>...);
+};
+
+template<class R, class C, class... T>
+struct rebind_placeholders_in_argument_impl<R (C::*)(T...) const>
+{
+ template<class Bindings>
+ using apply =
+ rebind_placeholders_in_argument_t<R, Bindings>
+ (rebind_placeholders_in_argument_t<C, Bindings>::*)
+ (rebind_placeholders_in_argument_t<T, Bindings>...) const;
+};
+
+template<template<class...> class T, class... U, class Bindings>
+struct rebind_placeholders<T<U...>, Bindings>
+{
+ typedef ::boost::type_erasure::detail::make_mp_list<Bindings> xBindings;
+ typedef T<rebind_placeholders_in_argument_t<U, xBindings>...> type;
+};
+
+template<class PrimitiveConcept, class Sig, class Bindings>
+struct rebind_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Bindings>
+{
+ typedef ::boost::type_erasure::detail::make_mp_list<Bindings> xBindings;
+ typedef vtable_adapter<
+ rebind_placeholders_t<PrimitiveConcept, xBindings>,
+ rebind_placeholders_in_argument_t<Sig, xBindings>
+ > type;
+};
+
+#else
+
template<class T, class Bindings>
struct rebind_placeholders_in_argument
{
@@ -62,6 +189,15 @@ struct rebind_placeholders_in_argument
>::type type;
};
+template<class PrimitiveConcept, class Sig, class Bindings>
+struct rebind_placeholders<vtable_adapter<PrimitiveConcept, Sig>, Bindings>
+{
+ typedef vtable_adapter<
+ typename rebind_placeholders<PrimitiveConcept, Bindings>::type,
+ typename rebind_placeholders_in_argument<Sig, Bindings>::type
+ > type;
+};
+
template<class T, class Bindings>
struct rebind_placeholders_in_argument<T&, Bindings>
{
@@ -134,6 +270,26 @@ struct rebind_placeholders_in_argument<R(T...), Bindings>
>::type type(typename rebind_placeholders_in_argument<T, Bindings>::type...);
};
+template<class R, class C, class... T, class Bindings>
+struct rebind_placeholders_in_argument<R (C::*)(T...), Bindings>
+{
+ typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
+ R,
+ Bindings
+ >::type (rebind_placeholders_in_argument<C, Bindings>::type::*type)
+ (typename rebind_placeholders_in_argument<T, Bindings>::type...);
+};
+
+template<class R, class C, class... T, class Bindings>
+struct rebind_placeholders_in_argument<R (C::*)(T...) const, Bindings>
+{
+ typedef typename ::boost::type_erasure::detail::rebind_placeholders_in_argument<
+ R,
+ Bindings
+ >::type (rebind_placeholders_in_argument<C, Bindings>::type::*type)
+ (typename rebind_placeholders_in_argument<T, Bindings>::type...) const;
+};
+
#else
#define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/rebind_placeholders.hpp>
@@ -142,6 +298,8 @@ struct rebind_placeholders_in_argument<R(T...), Bindings>
#endif
+#endif
+
}
}
}
diff --git a/boost/type_erasure/detail/storage.hpp b/boost/type_erasure/detail/storage.hpp
index 8f8bf865ea..8e572871f3 100644
--- a/boost/type_erasure/detail/storage.hpp
+++ b/boost/type_erasure/detail/storage.hpp
@@ -13,7 +13,7 @@
#include <boost/config.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/decay.hpp>
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
# include <utility> // for std::forward, std::move
@@ -37,11 +37,10 @@ struct storage
storage(storage&& other) : data(other.data) {}
storage& operator=(const storage& other) { data = other.data; return *this; }
template<class T>
- explicit storage(T&& arg) : data(new typename remove_cv<
- typename remove_reference<T>::type>::type(std::forward<T>(arg))) {}
+ explicit storage(T&& arg) : data(new typename boost::decay<T>::type(std::forward<T>(arg))) {}
#else
template<class T>
- explicit storage(const T& arg) : data(new T(arg)) {}
+ explicit storage(const T& arg) : data(new typename boost::decay<T>::type(arg)) {}
#endif
void* data;
};
diff --git a/boost/type_erasure/detail/vtable.hpp b/boost/type_erasure/detail/vtable.hpp
index b30a15a061..965ffcb390 100644
--- a/boost/type_erasure/detail/vtable.hpp
+++ b/boost/type_erasure/detail/vtable.hpp
@@ -17,6 +17,7 @@
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/expr_if.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
@@ -98,7 +99,7 @@ struct compare_vtable;
template<>
struct compare_vtable<> {
template<class S>
- static bool apply(const S& s1, const S& s2)
+ static bool apply(const S& /*s1*/, const S& /*s2*/)
{
return true;
}
@@ -151,9 +152,9 @@ struct vtable_storage<>
vtable_storage() = default;
template<class Bindings, class Src>
- void convert_from(const Src& src) {}
+ void convert_from(const Src& /*src*/) {}
- bool operator==(const vtable_storage& other) const
+ bool operator==(const vtable_storage& /*other*/) const
{ return true; }
};
@@ -249,12 +250,12 @@ struct BOOST_PP_CAT(vtable_storage, N)
BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_ENTRY, ~)
template<class Bindings, class Src>
- void convert_from(const Src& src)
+ void convert_from(const Src& BOOST_PP_EXPR_IF(N, src))
{
BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_CONVERT_ELEMENT, ~)
}
- bool operator==(const BOOST_PP_CAT(vtable_storage, N)& other) const
+ bool operator==(const BOOST_PP_CAT(vtable_storage, N)& BOOST_PP_EXPR_IF(N, other)) const
{ return true BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_COMPARE, ~); }
};
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>& 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<normalized> identity_map;
+#endif
::boost::type_erasure::dynamic_binding<placeholders> my_binding(
::boost::type_erasure::binding_of(arg),
::boost::type_erasure::make_binding<identity_map>());
@@ -153,7 +161,7 @@ R dynamic_any_cast_impl(Any& arg, const static_binding<Map>& 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 <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/punctuation/is_begin_parens.hpp>
+#include <boost/vmd/is_empty.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/mpl/eval_if.hpp>
@@ -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 <code>has_ ## function_name</code>
+ * \param function_name is the name of the function.
+ *
+ * The declaration of the concept is
+ * \code
+ * template<class Sig>
+ * 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<std::string(_self const&)> 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<int N>
+using make_index_list_t = typename ::boost::type_erasure::detail::make_index_list<N>::type;
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1900)
+
+template<class... T>
+struct first_placeholder_index_ :
+ ::boost::type_erasure::detail::first_placeholder_index<
+ ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
+ >
+{};
+template<class... T>
+using first_placeholder_index_t =
+ typename ::boost::type_erasure::detail::first_placeholder_index_<T...>::type;
+
+#else
+
+template<class... T>
+using first_placeholder_index_t =
+ typename ::boost::type_erasure::detail::first_placeholder_index<
+ ::boost::remove_cv_t< ::boost::remove_reference_t<T> >...
+ >::type;
+
+#endif
+
+template<class Base, class Tn, int I, class... T>
+using free_param_t =
+ typename ::boost::mpl::eval_if_c<(::boost::type_erasure::detail::first_placeholder_index_t<T...>::value == I),
+ ::boost::type_erasure::detail::maybe_const_this_param<Tn, Base>, \
+ ::boost::type_erasure::as_param<Base, Tn>
+ >::type;
+
+template<class Sig, class ID>
+struct free_interface_chooser
+{
+ template<class Base, template<class> class C, template<class...> class F>
+ using apply = Base;
+};
+
+template<class R, class... A>
+struct free_interface_chooser<
+ R(A...),
+ typename ::boost::type_erasure::detail::first_placeholder<
+ ::boost::remove_cv_t< ::boost::remove_reference_t<A> >...>::type>
+{
+ template<class Base, template<class> class C, template<class...> class F>
+ using apply = F<R(A...), Base,
+ ::boost::type_erasure::detail::make_index_list_t<sizeof...(A)> >;
+};
+
+template<class Sig, template<class> class C, template<class...> class F>
+struct free_choose_interface {
+ template<class Concept, class Base, class ID>
+ using apply = typename free_interface_chooser<Sig, ID>::template apply<Base, C, F>;
+};
/** 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<class Sig> \
+struct concept_name; \
+ \
+namespace boost_type_erasure_impl { \
+ \
+template<class Sig, class Base, class Idx> \
+struct concept_name ## _free_interface; \
+template<class R, class... T, class Base, int... I> \
+struct concept_name ## _free_interface<R(T...), Base, ::boost::type_erasure::index_list<I...> > : Base {\
+ friend ::boost::type_erasure::rebind_any_t<Base, R> \
+ function_name( \
+ ::boost::type_erasure::detail::free_param_t<Base, T, I, T...>... t) \
+ { \
+ return ::boost::type_erasure::call( \
+ concept_name<R(T...)>(), \
+ std::forward< ::boost::type_erasure::detail::free_param_t<Base, T, I, T...> >(t)...);\
+ } \
+}; \
+ \
+template<class Sig> \
+struct concept_name ## free; \
+ \
+template<class R, class... T> \
+struct concept_name ## free<R(T...)> { \
+ static R apply(T... t) \
+ { return function_name(std::forward<T>(t)...); } \
+}; \
+ \
+template<class... T> \
+struct concept_name ## free<void(T...)> { \
+ static void apply(T... t) \
+ { function_name(std::forward<T>(t)...); } \
+}; \
+ \
+} \
+ \
+template<class Sig> \
+struct concept_name : \
+ boost_type_erasure_impl::concept_name##free<Sig> \
+{}; \
+ \
+template<class Sig> \
+::boost::type_erasure::detail::free_choose_interface<Sig, concept_name, \
+ boost_type_erasure_impl::concept_name ## _free_interface> \
+boost_type_erasure_find_interface(concept_name<Sig>);
+
+#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<class Sig> \
@@ -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<class Sig>
- * 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 <boost/mpl/bool.hpp>
-#include <boost/type_traits/is_base_and_derived.hpp>
-#include <boost/type_erasure/placeholder.hpp>
namespace boost {
namespace type_erasure {
+#ifdef BOOST_TYPE_ERASURE_DOXYGEN
+
/** A metafunction that indicates whether a type is a @ref placeholder. */
template<class T>
-struct is_placeholder : ::boost::is_base_and_derived<placeholder, T> {};
+struct is_placeholder {};
+
+#else
+
+template<class T, class Enable = void>
+struct is_placeholder : ::boost::mpl::false_ {};
+
+template<class T>
+struct is_placeholder<T, typename T::_boost_type_erasure_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 <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/if.hpp>
@@ -19,6 +20,7 @@
#include <boost/mpl/has_key.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_erasure/detail/normalize.hpp>
+#include <boost/type_erasure/detail/check_map.hpp>
#include <boost/type_erasure/detail/rebind_placeholders.hpp>
#include <boost/type_erasure/static_binding.hpp>
@@ -26,10 +28,33 @@ namespace boost {
namespace type_erasure {
namespace detail {
+#ifdef BOOST_TYPE_ERASURE_USE_MP11
+
+template<class S, class K>
+struct mp_set_has_key : ::boost::mp11::mp_set_contains<S, K> {};
+
+template<class Super, class Bindings>
+struct is_subconcept_f
+{
+ template<class T>
+ using apply = ::boost::mp11::mp_set_contains<Super, ::boost::type_erasure::detail::rebind_placeholders_t<T, Bindings> >;
+};
+
+template<class Super>
+struct is_subconcept_f<Super, void>
+{
+ template<class T>
+ using apply = ::boost::mp11::mp_set_contains<Super, T>;
+};
+
+#endif
+
template<class Sub, class Super, class PlaceholderMap>
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<normalized_sub>::type
>::type type;
+#else
+ typedef ::boost::type_erasure::detail::normalize_concept_t<Super> super_set;
+
+ typedef ::boost::type_erasure::detail::get_placeholder_normalization_map_t<
+ Super
+ > placeholder_subs_super;
+
+ typedef ::boost::type_erasure::detail::normalize_concept_t<Sub> 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<PlaceholderMap, void>::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<super_set, bindings>::template apply
+ > type;
+#endif
};
}
@@ -92,13 +141,24 @@ struct is_subconcept_impl {
* are presumed to use the same set of placeholders.
*/
template<class Sub, class Super, class PlaceholderMap = void>
-struct is_subconcept : ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, PlaceholderMap>::type {
-};
+struct is_subconcept :
+ ::boost::mpl::and_<
+ ::boost::type_erasure::detail::check_map<Sub, PlaceholderMap>,
+ ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, PlaceholderMap>
+ >::type
+{};
#ifndef BOOST_TYPE_ERASURE_DOXYGEN
+template<class Sub, class Super>
+struct is_subconcept<Sub, Super, void> :
+ ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, void>::type
+{};
template<class Sub, class Super, class PlaceholderMap>
struct is_subconcept<Sub, Super, static_binding<PlaceholderMap> > :
- ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, PlaceholderMap>::type
+ ::boost::mpl::and_<
+ ::boost::type_erasure::detail::check_map<Sub, PlaceholderMap>,
+ ::boost::type_erasure::detail::is_subconcept_impl<Sub, Super, PlaceholderMap>
+ >::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 <boost/type_erasure/detail/member11.hpp>
+
+#ifndef BOOST_TYPE_ERASURE_MEMBER
+
#include <boost/detail/workaround.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/dec.hpp>
@@ -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 <code>has_ ## member</code>
* \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<class Sig, class T = _self>
- * 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<R(A...) const, T>
+ * is an alias for @c concept_name<R(A...), const T>.
+ *
+ * This macro can only be used at namespace scope.
+ *
+ * Example:
+ *
+ * \code
+ * namespace boost {
+ * BOOST_TYPE_ERASURE_MEMBER(push_back)
+ * }
+ * typedef boost::has_push_back<void(int)> 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<void(int), std::list<int> > {
+ * static void apply(std::list<int>& 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<void(int), _self> 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>(x)...
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+# define BOOST_TYPE_ERASURE_MEMBER_FORWARD_PARAMS(N, X, x) ::std::forward<X>(x)...
+# define BOOST_TYPE_ERASURE_MEMBER_FORWARD_REBIND(N) , ::std::forward<typename ::boost::type_erasure::as_param<Base, A>::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<typename ::boost::type_erasure::as_param<Base, A>::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<Base, A>::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 Concept, class Placeholder>
-class any;
-
/** INTERNAL ONLY */
#define BOOST_TYPE_ERASURE_UNARY_INPLACE_OPERATOR(name, op) \
template<class T = _self> \
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 Concept, class T>
class any;
template<class Concept>
class binding;
+#endif
+
namespace detail {
struct access;
@@ -75,16 +79,6 @@ struct placeholder_conversion<T&&, T&&> : 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<T&&, T&&> : 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<C, P> to @ref param<C, P1> is
- * a better conversion sequence than @ref any<C, P> to @ref param<C, P2>
+ * A conversion sequence from @ref any "any<C, P>" to @ref param "param<C, P1>" is
+ * a better conversion sequence than @ref any "any<C, P>" to @ref param "param<C, P2>"
* 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<Concept>& table)
+ : _impl(data, table)
+ {}
+
/** Returns the stored @ref any. */
any<Concept, T> get() const { return _impl; }
private:
any<Concept, T> _impl;
};
-#ifndef BOOST_NO_FUNCTION_REFERENCE_QUALIFIERS
+#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) && !defined(BOOST_TYPE_ERASURE_DOXYGEN)
template<class Concept, class T>
class param<Concept, const T&> {
@@ -199,7 +199,21 @@ public:
param(U& u, typename boost::enable_if< ::boost::is_same<U, const any<Concept, T> > >::type* = 0) : _impl(u) {}
any<Concept, const T&> get() const { return _impl; }
protected:
- any<Concept, const T&> _impl;
+ struct _impl_t {
+ _impl_t(const ::boost::type_erasure::detail::storage& data_,
+ const ::boost::type_erasure::binding<Concept>& table_)
+ : table(table_), data(data_)
+ {}
+ _impl_t(const any<Concept, T>& 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<Concept>& table;
+ ::boost::type_erasure::detail::storage data;
+ } _impl;
};
template<class Concept, class T>
@@ -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<Any>::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<class Any, class T>
+using as_param_t = typename ::boost::type_erasure::as_param<Any, T>::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 Concept, class T>
class any;
template<class Concept, class T>
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<Concept, T> >
typedef T type;
};
+#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
+
+template<class T>
+using placeholder_of_t = typename ::boost::type_erasure::placeholder_of<T>::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 Concept, class T>
class any;
+#endif
/**
* A metafunction that changes the @ref placeholder of
@@ -36,6 +38,7 @@ class any;
* \code
* rebind_any<any<Concept>, _a>::type -> any<Concept, _a>
* rebind_any<any<Concept>, _b&>::type -> any<Concept, _b&>
+ * rebind_any<any<Concept>, _c&&>::type -> any<Concept, _c&&>
* rebind_any<any<Concept>, int>::type -> int
* \endcode
*
@@ -62,6 +65,13 @@ struct rebind_any
#endif
};
+#ifndef BOOST_NO_CXX11_TEMPLATE_ALIASES
+
+template<class Any, class T>
+using rebind_any_t = typename ::boost::type_erasure::rebind_any<Any, T>::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<class P>
void operator()(P) {
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
key->push_back(&typeid(typename ::boost::mpl::at<Map, P>::type));
+#else
+ key->push_back(&typeid(::boost::mp11::mp_second< ::boost::mp11::mp_map_find<Map, P> >));
+#endif
}
key_type* key;
};
@@ -94,7 +98,11 @@ struct register_function {
template<class F>
void operator()(F) {
key_type key;
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mpl::set0<> >::type placeholders;
+#else
+ typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mp11::mp_list<> >::type placeholders;
+#endif
typedef typename ::boost::mpl::fold<
placeholders,
::boost::mpl::map0<>,
@@ -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<class Concept, class Map>
void register_binding(const static_binding<Map>&)
@@ -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 Concept>
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<U>(arg)...);
}
+#ifndef BOOST_TYPE_ERASURE_USE_MP11
+
template<class Op, class... U>
void require_match(
const Op& op,
@@ -129,6 +133,25 @@ void require_match(
#else
+template<class Op, class... U>
+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<Op>::type
+ >,
+ ::boost::mp11::mp_list< ::boost::remove_reference_t<U>...> >
+ > cond;
+ ::boost::type_erasure::detail::require_match_impl(cond, op, ::std::forward<U>(arg)...);
+}
+
+#endif
+
+#else
+
#define BOOST_PP_FILENAME_1 <boost/type_erasure/require_match.hpp>
#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<class Map>
-struct static_binding {};
+struct static_binding { typedef Map map_type; };
/**
* A convenience function to prevent constructor calls