@@ -467,10 +467,6 @@ namespace __variant
template<typename... _Types>
struct _Variant_storage<false, _Types...>
{
- template<typename _Tp>
- static constexpr size_t __index_of
- = __detail::__variant::__index_of_v<_Tp, _Types...>;
-
constexpr
_Variant_storage()
: _M_index(static_cast<__index_type>(variant_npos))
@@ -517,10 +513,6 @@ namespace __variant
template<typename... _Types>
struct _Variant_storage<true, _Types...>
{
- template<typename _Tp>
- static constexpr size_t __index_of
- = __detail::__variant::__index_of_v<_Tp, _Types...>;
-
constexpr
_Variant_storage()
: _M_index(static_cast<__index_type>(variant_npos))
@@ -560,35 +552,6 @@ namespace __variant
using _Variant_storage_alias =
_Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
- template<typename _Tp, typename _Up>
- _GLIBCXX20_CONSTEXPR
- void
- __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem)
- {
- using _Type = __remove_cvref_t<_Up>;
-
- if constexpr (!is_same_v<_Type, __variant_cookie>)
- {
- using _Lhs = remove_reference_t<_Tp>;
- std::_Construct(std::__addressof(__lhs._M_u),
- in_place_index<_Lhs::template __index_of<_Type>>,
- std::forward<_Up>(__rhs_mem));
- }
- }
-
- template<typename... _Types, typename _Tp, typename _Up>
- _GLIBCXX20_CONSTEXPR
- void
- __variant_construct(_Tp&& __lhs, _Up&& __rhs)
- {
- __lhs._M_index = __rhs._M_index;
- __variant::__raw_visit([&__lhs](auto&& __rhs_mem) mutable
- {
- __variant_construct_single(std::forward<_Tp>(__lhs),
- std::forward<decltype(__rhs_mem)>(__rhs_mem));
- }, __variant_cast<_Types...>(std::forward<_Up>(__rhs)));
- }
-
// The following are (Copy|Move) (ctor|assign) layers for forwarding
// triviality and handling non-trivial SMF behaviors.
@@ -602,7 +565,15 @@ namespace __variant
_Copy_ctor_base(const _Copy_ctor_base& __rhs)
noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor)
{
- __variant_construct<_Types...>(*this, __rhs);
+ __variant::__raw_idx_visit(
+ [this](auto&& __rhs_mem, auto __rhs_index) mutable
+ {
+ constexpr size_t __j = __rhs_index;
+ if constexpr (__j != variant_npos)
+ std::_Construct(std::__addressof(this->_M_u),
+ in_place_index<__j>, __rhs_mem);
+ }, __variant_cast<_Types...>(__rhs));
+ this->_M_index = __rhs._M_index;
}
_Copy_ctor_base(_Copy_ctor_base&&) = default;
@@ -631,27 +602,17 @@ namespace __variant
_Move_ctor_base(_Move_ctor_base&& __rhs)
noexcept(_Traits<_Types...>::_S_nothrow_move_ctor)
{
- __variant_construct<_Types...>(*this, std::move(__rhs));
+ __variant::__raw_idx_visit(
+ [this](auto&& __rhs_mem, auto __rhs_index) mutable
+ {
+ constexpr size_t __j = __rhs_index;
+ if constexpr (__j != variant_npos)
+ std::_Construct(std::__addressof(this->_M_u),
+ in_place_index<__j>,
+ std::forward<decltype(__rhs_mem)>(__rhs_mem));
+ }, __variant_cast<_Types...>(std::move(__rhs)));
+ this->_M_index = __rhs._M_index;
}
-
- template<typename _Up>
- _GLIBCXX20_CONSTEXPR
- void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
- {
- this->_M_reset();
- __variant_construct_single(*this, std::forward<_Up>(__rhs));
- this->_M_index = __rhs_index;
- }
-
- template<typename _Up>
- _GLIBCXX20_CONSTEXPR
- void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
- {
- this->_M_reset();
- __variant_construct_single(*this, __rhs);
- this->_M_index = __rhs_index;
- }
-
_Move_ctor_base(const _Move_ctor_base&) = default;
_Move_ctor_base& operator=(const _Move_ctor_base&) = default;
_Move_ctor_base& operator=(_Move_ctor_base&&) = default;
@@ -662,24 +623,6 @@ namespace __variant
{
using _Base = _Copy_ctor_alias<_Types...>;
using _Base::_Base;
-
- template<typename _Up>
- _GLIBCXX20_CONSTEXPR
- void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
- {
- this->_M_reset();
- __variant_construct_single(*this, std::forward<_Up>(__rhs));
- this->_M_index = __rhs_index;
- }
-
- template<typename _Up>
- _GLIBCXX20_CONSTEXPR
- void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
- {
- this->_M_reset();
- __variant_construct_single(*this, __rhs);
- this->_M_index = __rhs_index;
- }
};
template<typename... _Types>
@@ -709,14 +652,19 @@ namespace __variant
using __rhs_type = __remove_cvref_t<decltype(__rhs_mem)>;
if constexpr (is_nothrow_copy_constructible_v<__rhs_type>
|| !is_nothrow_move_constructible_v<__rhs_type>)
- // The standard says this->emplace<__rhs_type>(__rhs_mem)
- // should be used here, but _M_destructive_copy is
- // equivalent in this case. Either copy construction
- // doesn't throw, so _M_destructive_copy gives strong
- // exception safety guarantee, or both copy construction
- // and move construction can throw, so emplace only gives
- // basic exception safety anyway.
- this->_M_destructive_copy(__rhs_index, __rhs_mem);
+ {
+ // The standard says emplace<__rhs_index>(__rhs_mem)
+ // should be used here, but this is equivalent. Either
+ // copy construction doesn't throw, so we have strong
+ // exception safety guarantee, or both copy construction
+ // and move construction can throw, so emplace only
+ // gives basic exception safety anyway.
+ this->_M_reset();
+ std::_Construct(std::__addressof(this->_M_u),
+ in_place_index<__rhs_index>,
+ __rhs_mem);
+ this->_M_index = __rhs_index;
+ }
else
__variant_cast<_Types...>(*this)
= variant<_Types...>(std::in_place_index<__rhs_index>,
@@ -1715,17 +1663,24 @@ namespace __variant
}
else
{
+ constexpr size_t __j = __rhs_index;
if (!this->valueless_by_exception()) [[__likely__]]
{
auto __tmp(std::move(__rhs_mem));
__rhs = std::move(*this);
- this->_M_destructive_move(__rhs_index,
- std::move(__tmp));
+ this->_M_reset();
+ std::_Construct(std::__addressof(this->_M_u),
+ in_place_index<__j>,
+ std::move(__tmp));
+ this->_M_index = __j;
}
else
{
- this->_M_destructive_move(__rhs_index,
- std::move(__rhs_mem));
+ this->_M_reset();
+ std::_Construct(std::__addressof(this->_M_u),
+ in_place_index<__j>,
+ std::move(__rhs_mem));
+ this->_M_index = __j;
__rhs._M_reset();
}
}
new file mode 100644
@@ -0,0 +1,71 @@
+// { dg-do compile { target c++17 } }
+#include <variant>
+
+void
+test01()
+{
+ struct X {
+ ~X() { } // non-trivial
+ };
+
+ std::variant<const int, const X> v;
+ auto vv = v;
+}
+
+#if __cpp_lib_variant >= 202106L // P2231R1 constexpr destruction in variant
+constexpr bool
+test02()
+{
+ struct Y {
+ constexpr ~Y() { } // non-trivial
+ };
+ using V = std::variant<int, const int, const Y, Y>;
+
+ V v1(std::in_place_index<1>, 1);
+ V vv1 = v1;
+ if (vv1.index() != v1.index())
+ return false;
+
+ V v2(std::in_place_index<2>);
+ V vv2 = v2;
+ if (vv2.index() != v2.index())
+ return false;
+
+ return true;
+}
+static_assert( test02() );
+
+constexpr bool
+test03()
+{
+ struct Y {
+ constexpr ~Y() { } // non-trivial
+ };
+ using V = std::variant<int, int, Y, Y>;
+
+ V v1(std::in_place_index<1>, 1);
+ V vv1 = v1;
+ if (vv1.index() != v1.index())
+ return false;
+ vv1 = v1;
+ if (vv1.index() != v1.index())
+ return false;
+ vv1 = std::move(v1);
+ if (vv1.index() != v1.index())
+ return false;
+
+ V v2(std::in_place_index<2>);
+ V vv2 = v2;
+ if (vv2.index() != v2.index())
+ return false;
+ vv2 = v2;
+ if (vv2.index() != v2.index())
+ return false;
+ vv2 = std::move(v2);
+ if (vv2.index() != v2.index())
+ return false;
+
+ return true;
+}
+static_assert( test03() );
+#endif