diff --git a/include/boost/variant/variant.hpp b/include/boost/variant/variant.hpp index 5cfa351b..61ed0050 100644 --- a/include/boost/variant/variant.hpp +++ b/include/boost/variant/variant.hpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -258,66 +260,170 @@ struct is_variant_move_noexcept_assignable { #endif // BOOST_NO_CXX11_NOEXCEPT /////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction is_variant_constructible_from -// -// Derives from true_type if at least one variant's type is constructible from T. -// -template -struct is_constructible_ext: - boost::mpl::or_< - boost::is_constructible< - T1, - T2 - >, - boost::is_constructible< - T1, - typename boost::add_lvalue_reference::type - > +template +struct add_clref +{ + typedef typename boost::add_lvalue_reference< + typename boost::add_const::type + >::type type; +}; + +template +struct unwrap_reference_content +{ + typedef T type; +}; + +template +struct unwrap_reference_content > +{ + typedef T type; +}; + +template +struct wrapper +{ + typedef wrapper type; + typedef typename unwrap_reference_content::type wrapped_type; +}; + +struct overload_FUN_base +{ + enum { value = 0 }; + void fun(); +}; + +template +struct overload_FUN : T1, T2 +{ + typedef overload_FUN type; + enum { value = T1::value + 1 }; + typedef char result[value]; + using T1::fun; + static result& fun(typename T2::wrapped_type); +}; + +template +struct FUN_index +{ + enum { value = 0 }; +}; + +template +struct FUN_index()))> + >::type> +{ + enum { value = sizeof(OverloadSet::fun(boost::declval())) }; +}; + +template +struct make_FUN_overload_set: + mpl::inherit_linearly< + TypeList, + overload_FUN >, + overload_FUN_base + > +{}; + +template +struct is_variant_constructible_from_type: + mpl::bool_< + FUN_index::type, T>::value != 0 > {}; template struct is_variant_constructible_from: - boost::mpl::not_< boost::is_same< - typename boost::mpl::find_if< - Types, - is_constructible_ext + is_variant_constructible_from_type +{}; + +template +struct is_variant_constructible_from_variant: + boost::is_same< + typename mpl::find_if< + VariantTypes, + mpl::not_< is_variant_constructible_from< mpl::_1, Types> > >::type, - typename boost::mpl::end::type - > > + typename mpl::end::type + > {}; template struct is_variant_constructible_from< boost::variant, Types >: - boost::is_same< - typename boost::mpl::find_if< + mpl::or_< + is_variant_constructible_from_type, Types>, + is_variant_constructible_from_variant< typename boost::variant::recursive_enabled_types, - mpl::not_< is_variant_constructible_from< boost::mpl::_1, Types> > - >::type, - typename boost::mpl::end< typename boost::variant::recursive_enabled_types >::type - > + Types + > + >::type {}; template struct is_variant_constructible_from< const boost::variant& , Types >: - is_variant_constructible_from, Types > + mpl::or_< + is_variant_constructible_from_type, Types>, + is_variant_constructible_from_variant< + typename mpl::transform< + typename boost::variant::recursive_enabled_types, + add_clref + >::type, + Types + > + >::type {}; template struct is_variant_constructible_from< boost::variant& , Types >: - is_variant_constructible_from, Types > + mpl::or_< + is_variant_constructible_from_type, Types>, + is_variant_constructible_from_variant< + typename mpl::transform< + typename boost::variant::recursive_enabled_types, + boost::add_lvalue_reference + >::type, + Types + > + >::type {}; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +template +struct add_crref +{ + typedef typename boost::add_rvalue_reference< + typename boost::add_const::type + >::type type; +}; + template struct is_variant_constructible_from< boost::variant&& , Types >: - is_variant_constructible_from, Types > + mpl::or_< + is_variant_constructible_from_type, Types>, + is_variant_constructible_from_variant< + typename mpl::transform< + typename boost::variant::recursive_enabled_types, + boost::add_rvalue_reference + >::type, + Types + > + >::type {}; template struct is_variant_constructible_from< boost::variant const && , Types >: - is_variant_constructible_from, Types > + mpl::or_< + is_variant_constructible_from_type, Types>, + is_variant_constructible_from_variant< + typename mpl::transform< + typename boost::variant::recursive_enabled_types, + add_crref + >::type, + Types + > + >::type {}; #endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCE diff --git a/test/recursive_variant_test.cpp b/test/recursive_variant_test.cpp index 67485d21..3507adbe 100644 --- a/test/recursive_variant_test.cpp +++ b/test/recursive_variant_test.cpp @@ -363,7 +363,7 @@ void test_recursive_variant_from_variant() typedef boost::variant Atom; typedef boost::variant > Variant; - BOOST_STATIC_ASSERT(!boost::is_constructible::value); + BOOST_STATIC_ASSERT(boost::is_constructible::value); BOOST_STATIC_ASSERT(boost::is_constructible, Atom>::value); }