diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index 0df00df..cf41d4a 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -376,9 +376,10 @@ template struct overload: overload #if BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) -template struct resolve_overload_type_impl +template using resolve_overload_type_ = decltype( overload()(std::declval()) ); + +template struct resolve_overload_type_impl: mp_defer< resolve_overload_type_, U, T... > { - using type = decltype( overload()(std::declval()) ); }; template using resolve_overload_type = typename resolve_overload_type_impl::type::type; @@ -991,6 +992,104 @@ public: } using variant_base::_get_impl; + + // converting constructors (extension) + + template..., mp_contains, U>...>, void> > + variant( variant const& r ) + noexcept( mp_all...>::value ) + { + mp_for_index( r.index(), [&]( auto I ){ + + using J = mp_find, mp_at_c, I>>; + + ::new( static_cast(this) ) variant_base( J{}, r._get_impl( I ) ); + + }); + } + + template..., mp_contains, U>...>, void> > + variant( variant && r ) + noexcept( mp_all...>::value ) + { + mp_for_index( r.index(), [&]( auto I ){ + + using J = mp_find, mp_at_c, I>>; + + ::new( static_cast(this) ) variant_base( J{}, std::move( r._get_impl( I ) ) ); + + }); + } + + // subset (extension) + +private: + + template> static variant _subset_impl( mp_size_t, V && v ) + { + return variant( in_place_index, std::forward(v) ); + } + + template static variant _subset_impl( mp_size_t, V && /*v*/ ) + { + throw bad_variant_access(); + } + +public: + + template..., mp_contains, U>...>, void> > + constexpr variant subset() & + { + return mp_for_index( index(), [&]( auto I ){ + + using J = mp_find, mp_at_c, I>>; + + return _subset_impl( J{}, get( *this ) ); + + }); + } + + template..., mp_contains, U>...>, void> > + constexpr variant subset() const& + { + return mp_for_index( index(), [&]( auto I ){ + + using J = mp_find, mp_at_c, I>>; + + return _subset_impl( J{}, get( *this ) ); + + }); + } + + template..., mp_contains, U>...>, void> > + constexpr variant subset() && + { + return mp_for_index( index(), [&]( auto I ){ + + using J = mp_find, mp_at_c, I>>; + + return _subset_impl( J{}, get( std::move(*this) ) ); + + }); + } + + template..., mp_contains, U>...>, void> > + constexpr variant subset() const&& + { + return mp_for_index( index(), [&]( auto I ){ + + using J = mp_find, mp_at_c, I>>; + + return _subset_impl( J{}, get( std::move(*this) ) ); + + }); + } }; // relational operators diff --git a/test/variant_copy_construct.cpp b/test/variant_copy_construct.cpp index 473d8a2..6762776 100644 --- a/test/variant_copy_construct.cpp +++ b/test/variant_copy_construct.cpp @@ -121,7 +121,12 @@ int main() BOOST_TEST_TRAIT_FALSE((std::is_nothrow_copy_constructible>)); BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible>)); + +#if !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + BOOST_TEST_TRAIT_FALSE((std::is_copy_constructible>)); + +#endif } return boost::report_errors(); diff --git a/test/variant_move_construct.cpp b/test/variant_move_construct.cpp index e3d8e98..4561ebd 100644 --- a/test/variant_move_construct.cpp +++ b/test/variant_move_construct.cpp @@ -122,7 +122,12 @@ int main() BOOST_TEST_TRAIT_FALSE((std::is_nothrow_move_constructible>)); BOOST_TEST_TRAIT_TRUE((std::is_move_constructible>)); + +#if !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + BOOST_TEST_TRAIT_FALSE((std::is_move_constructible>)); + +#endif } return boost::report_errors();