Commit 337d1fec by Ville Voutilainen Committed by Ville Voutilainen

Don't revisit a variant we are already visiting.

* include/std/variant (__variant_construct_single): New.
(__variant_construct): Use it.
(_M_destructive_move): Likewise.
(_M_destructive_copy): Likewise.
(_Copy_assign_base::operator=): Adjust.
(_Move_assign_base::operator=): Likewise.
(swap): Likewise.

From-SVN: r269996
parent c7a53bdb
2019-03-28 Ville Voutilainen <ville.voutilainen@gmail.com>
Don't revisit a variant we are already visiting.
* include/std/variant (__variant_construct_single): New.
(__variant_construct): Use it.
(_M_destructive_move): Likewise.
(_M_destructive_copy): Likewise.
(_Copy_assign_base::operator=): Adjust.
(_Move_assign_base::operator=): Likewise.
(swap): Likewise.
2019-03-26 Jonathan Wakely <jwakely@redhat.com> 2019-03-26 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/85965 PR libstdc++/85965
......
...@@ -428,20 +428,25 @@ namespace __variant ...@@ -428,20 +428,25 @@ namespace __variant
using _Variant_storage_alias = using _Variant_storage_alias =
_Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>;
template<typename _Tp, typename _Up>
void __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem)
{
void* __storage = std::addressof(__lhs._M_u);
using _Type = remove_reference_t<decltype(__rhs_mem)>;
if constexpr (!is_same_v<_Type, __variant_cookie>)
::new (__storage)
_Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));
}
template<typename... _Types, typename _Tp, typename _Up> template<typename... _Types, typename _Tp, typename _Up>
void __variant_construct(_Tp&& __lhs, _Up&& __rhs) void __variant_construct(_Tp&& __lhs, _Up&& __rhs)
{ {
__lhs._M_index = __rhs._M_index; __lhs._M_index = __rhs._M_index;
void* __storage = std::addressof(__lhs._M_u); __do_visit([&__lhs](auto&& __rhs_mem) mutable
__do_visit([__storage](auto&& __rhs_mem) mutable
-> __detail::__variant::__variant_cookie -> __detail::__variant::__variant_cookie
{ {
using _Type = remove_reference_t<decltype(__rhs_mem)>; __variant_construct_single(std::forward<_Tp>(__lhs),
if constexpr (is_same_v<__remove_cvref_t<decltype(__rhs_mem)>, std::forward<decltype(__rhs_mem)>(__rhs_mem));
remove_cv_t<_Type>>
&& !is_same_v<_Type, __variant_cookie>)
::new (__storage)
_Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));
return {}; return {};
}, __variant_cast<_Types...>(std::forward<decltype(__rhs)>(__rhs))); }, __variant_cast<_Types...>(std::forward<decltype(__rhs)>(__rhs)));
} }
...@@ -490,13 +495,15 @@ namespace __variant ...@@ -490,13 +495,15 @@ namespace __variant
std::forward<_Move_ctor_base>(__rhs)); std::forward<_Move_ctor_base>(__rhs));
} }
void _M_destructive_move(_Move_ctor_base&& __rhs) template<typename _Up>
void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
{ {
this->_M_reset(); this->_M_reset();
this->_M_index = __rhs_index;
__try __try
{ {
__variant_construct<_Types...>(*this, __variant_construct_single(*this,
std::forward<_Move_ctor_base>(__rhs)); std::forward<_Up>(__rhs));
} }
__catch (...) __catch (...)
{ {
...@@ -505,12 +512,14 @@ namespace __variant ...@@ -505,12 +512,14 @@ namespace __variant
} }
} }
void _M_destructive_copy(const _Move_ctor_base& __rhs) template<typename _Up>
void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
{ {
this->_M_reset(); this->_M_reset();
this->_M_index = __rhs_index;
__try __try
{ {
__variant_construct<_Types...>(*this, __rhs); __variant_construct_single(*this, __rhs);
} }
__catch (...) __catch (...)
{ {
...@@ -530,16 +539,20 @@ namespace __variant ...@@ -530,16 +539,20 @@ namespace __variant
using _Base = _Copy_ctor_alias<_Types...>; using _Base = _Copy_ctor_alias<_Types...>;
using _Base::_Base; using _Base::_Base;
void _M_destructive_move(_Move_ctor_base&& __rhs) template<typename _Up>
void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs)
{ {
this->_M_reset(); this->_M_reset();
__variant_construct<_Types...>(*this, this->_M_index = __rhs_index;
std::forward<_Move_ctor_base>(__rhs)); __variant_construct_single(*this,
std::forward<_Up>(__rhs));
} }
void _M_destructive_copy(const _Move_ctor_base& __rhs) template<typename _Up>
void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs)
{ {
this->_M_reset(); this->_M_reset();
__variant_construct<_Types...>(*this, __rhs); this->_M_index = __rhs_index;
__variant_construct_single(*this, __rhs);
} }
}; };
...@@ -580,12 +593,13 @@ namespace __variant ...@@ -580,12 +593,13 @@ namespace __variant
if constexpr (is_nothrow_copy_constructible_v<__rhs_type> if constexpr (is_nothrow_copy_constructible_v<__rhs_type>
|| !is_nothrow_move_constructible_v<__rhs_type>) || !is_nothrow_move_constructible_v<__rhs_type>)
{ {
this->_M_destructive_copy(__rhs); this->_M_destructive_copy(__rhs._M_index, __rhs_mem);
} }
else else
{ {
_Copy_assign_base __tmp(__rhs); auto __tmp(__rhs_mem);
this->_M_destructive_move(std::move(__tmp)); this->_M_destructive_move(__rhs._M_index,
std::move(__tmp));
} }
} }
else else
...@@ -641,8 +655,8 @@ namespace __variant ...@@ -641,8 +655,8 @@ namespace __variant
} }
else else
{ {
_Move_assign_base __tmp(std::move(__rhs)); auto __tmp(std::move(__rhs_mem));
this->_M_destructive_move(std::move(__tmp)); this->_M_destructive_move(__rhs._M_index, std::move(__tmp));
} }
return {}; return {};
}, __variant_cast<_Types...>(*this), __variant_cast<_Types...>(__rhs)); }, __variant_cast<_Types...>(*this), __variant_cast<_Types...>(__rhs));
...@@ -1409,21 +1423,26 @@ namespace __variant ...@@ -1409,21 +1423,26 @@ namespace __variant
remove_reference_t<decltype(__this_mem)>, remove_reference_t<decltype(__this_mem)>,
__detail::__variant::__variant_cookie>) __detail::__variant::__variant_cookie>)
{ {
this->_M_destructive_move(std::move(__rhs)); this->_M_destructive_move(__rhs.index(),
std::move(__rhs_mem));
__rhs._M_reset(); __rhs._M_reset();
} }
else if constexpr (is_same_v< else if constexpr (is_same_v<
remove_reference_t<decltype(__rhs_mem)>, remove_reference_t<decltype(__rhs_mem)>,
__detail::__variant::__variant_cookie>) __detail::__variant::__variant_cookie>)
{ {
__rhs._M_destructive_move(std::move(*this)); __rhs._M_destructive_move(this->index(),
std::move(__this_mem));
this->_M_reset(); this->_M_reset();
} }
else else
{ {
auto __tmp = std::move(__rhs); auto __tmp(std::move(__rhs_mem));
__rhs._M_destructive_move(std::move(*this)); auto __idx = __rhs.index();
this->_M_destructive_move(std::move(__tmp)); __rhs._M_destructive_move(this->index(),
std::move(__this_mem));
this->_M_destructive_move(__idx,
std::move(__tmp));
} }
} }
return {}; return {};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment