diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index fe28315..d930e58 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -1054,34 +1054,53 @@ template struct is_nothrow_swappable: mp11::mp_valid class variant: private detail::variant_base +namespace detail { -private: +template struct variant_copy_base_impl; + +template using variant_copy_base = variant_copy_base_impl< + mp11::mp_all< + std::is_trivially_destructible..., + is_trivially_copy_constructible..., + is_trivially_move_constructible..., + is_trivially_copy_assignable..., + is_trivially_move_assignable...>::value, T...>; + +template struct variant_copy_base_impl: public variant_base +{ using variant_base = detail::variant_base; + using variant_base::variant_base; + + variant_copy_base_impl() = default; + variant_copy_base_impl( variant_copy_base_impl const& ) = default; + variant_copy_base_impl( variant_copy_base_impl && ) = default; + variant_copy_base_impl& operator=( variant_copy_base_impl const& ) = default; + variant_copy_base_impl& operator=( variant_copy_base_impl && ) = default; +}; + +template struct variant_copy_base_impl: public variant_base +{ + using variant_base = detail::variant_base; + using variant_base::variant_base; private: - variant( variant const volatile& r ) = delete; - variant& operator=( variant const volatile& r ) = delete; + variant_copy_base_impl( variant_copy_base_impl const volatile& r ) = delete; + variant_copy_base_impl& operator=( variant_copy_base_impl const volatile& r ) = delete; public: // constructors - template> >, E1>> - constexpr variant() - noexcept( std::is_nothrow_default_constructible< mp11::mp_first> >::value ) - : variant_base( mp11::mp_size_t<0>() ) - { - } + variant_copy_base_impl() = default; template...>, E1> > - constexpr variant( variant const& r ) noexcept + constexpr variant_copy_base_impl( variant_copy_base_impl const& r ) noexcept : variant_base( static_cast(r) ) { } @@ -1091,7 +1110,7 @@ private: struct L1 { variant_base * this_; - variant const & r; + variant_copy_base_impl const & r; template void operator()( I i ) const { @@ -1105,7 +1124,7 @@ public: class E2 = mp11::mp_if...>>, E1>, class E3 = mp11::mp_if...>, E1> > - variant( variant const& r ) + variant_copy_base_impl( variant_copy_base_impl const& r ) noexcept( mp11::mp_all...>::value ) { mp11::mp_with_index( r.index(), L1{ this, r } ); @@ -1114,17 +1133,19 @@ public: template...>, E1> > - constexpr variant( variant && r ) noexcept + constexpr variant_copy_base_impl( variant_copy_base_impl && r ) noexcept : variant_base( static_cast(r) ) { } + // assignment + private: struct L2 { variant_base * this_; - variant & r; + variant_copy_base_impl & r; template void operator()( I i ) const { @@ -1138,12 +1159,107 @@ public: class E2 = mp11::mp_if...>>, E1>, class E3 = mp11::mp_if...>, E1> > - variant( variant && r ) + variant_copy_base_impl( variant_copy_base_impl && r ) noexcept( mp11::mp_all...>::value ) { mp11::mp_with_index( r.index(), L2{ this, r } ); } + template..., detail::is_trivially_copy_constructible..., detail::is_trivially_copy_assignable...>, E1> + > + BOOST_CXX14_CONSTEXPR variant_copy_base_impl& operator=( variant_copy_base_impl const & r ) noexcept + { + static_cast( *this ) = static_cast( r ); + return *this; + } + +private: + + struct L3 + { + variant_copy_base_impl * this_; + variant_copy_base_impl const & r; + + template void operator()( I i ) const + { + this_->variant_base::template emplace( r._get_impl( i ) ); + } + }; + +public: + + template..., detail::is_trivially_copy_constructible..., detail::is_trivially_copy_assignable...>>, E1>, + class E3 = mp11::mp_if..., std::is_copy_assignable...>, E1> + > + BOOST_CXX14_CONSTEXPR variant_copy_base_impl& operator=( variant_copy_base_impl const & r ) + noexcept( mp11::mp_all...>::value ) + { + mp11::mp_with_index( r.index(), L3{ this, r } ); + return *this; + } + + template..., detail::is_trivially_move_constructible..., detail::is_trivially_move_assignable...>, E1> + > + BOOST_CXX14_CONSTEXPR variant_copy_base_impl& operator=( variant_copy_base_impl && r ) noexcept + { + static_cast( *this ) = static_cast( r ); + return *this; + } + +private: + + struct L4 + { + variant_copy_base_impl * this_; + variant_copy_base_impl & r; + + template void operator()( I i ) const + { + this_->variant_base::template emplace( std::move( r._get_impl( i ) ) ); + } + }; + +public: + + template..., detail::is_trivially_move_constructible..., detail::is_trivially_move_assignable...>>, E1>, + class E3 = mp11::mp_if..., std::is_move_assignable...>, E1> + > + variant_copy_base_impl& operator=( variant_copy_base_impl && r ) + noexcept( mp11::mp_all...>::value ) + { + mp11::mp_with_index( r.index(), L4{ this, r } ); + return *this; + } +}; + +} // namespace detail + +// variant + +template class variant: private detail::variant_copy_base +{ +private: + + using variant_base = detail::variant_copy_base; + +public: + + // constructors + + template> >, E1>> + constexpr variant() + noexcept( std::is_nothrow_default_constructible< mp11::mp_first> >::value ) + : variant_base( mp11::mp_size_t<0>() ) + { + } + + variant( variant const& ) = default; + variant( variant && ) = default; + template::type, class E1 = typename std::enable_if< !std::is_same::value && !detail::is_in_place_index::value && !detail::is_in_place_type::value >::type, @@ -1177,75 +1293,9 @@ public: } // assignment - template..., detail::is_trivially_copy_constructible..., detail::is_trivially_copy_assignable...>, E1> - > - BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r ) noexcept - { - static_cast( *this ) = static_cast( r ); - return *this; - } -private: - - struct L3 - { - variant * this_; - variant const & r; - - template void operator()( I i ) const - { - this_->variant_base::template emplace( r._get_impl( i ) ); - } - }; - -public: - - template..., detail::is_trivially_copy_constructible..., detail::is_trivially_copy_assignable...>>, E1>, - class E3 = mp11::mp_if..., std::is_copy_assignable...>, E1> - > - BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r ) - noexcept( mp11::mp_all...>::value ) - { - mp11::mp_with_index( r.index(), L3{ this, r } ); - return *this; - } - - template..., detail::is_trivially_move_constructible..., detail::is_trivially_move_assignable...>, E1> - > - BOOST_CXX14_CONSTEXPR variant& operator=( variant && r ) noexcept - { - static_cast( *this ) = static_cast( r ); - return *this; - } - -private: - - struct L4 - { - variant * this_; - variant & r; - - template void operator()( I i ) const - { - this_->variant_base::template emplace( std::move( r._get_impl( i ) ) ); - } - }; - -public: - - template..., detail::is_trivially_move_constructible..., detail::is_trivially_move_assignable...>>, E1>, - class E3 = mp11::mp_if..., std::is_move_assignable...>, E1> - > - variant& operator=( variant && r ) - noexcept( mp11::mp_all...>::value ) - { - mp11::mp_with_index( r.index(), L4{ this, r } ); - return *this; - } + variant& operator=( variant const& ) = default; + variant& operator=( variant && ) = default; template::type, variant>::value>::type,