Remove some more code duplication in std::optional

Hoist the duplicated code from the _Optional_payload partial
specializations into the _Optional_payload_base base class.

	* include/std/optional (_Optional_payload_base::_M_copy_assign): New
	member function to perform non-trivial assignment.
	(_Optional_payload_base::_M_move_assign): Likewise.
	(_Optional_payload<T, true, false, true>::operator=)
	(_Optional_payload<T, true, true, false>::operator=)
	(_Optional_payload<T, true, false, false>::operator=): Call
	_M_copy_assign and/or _M_move_assign to do non-trivial assignments.

From-SVN: r267761
This commit is contained in:
Jonathan Wakely 2019-01-09 10:40:49 +00:00 committed by Jonathan Wakely
parent 5ed895a74a
commit 50b0a3d672
2 changed files with 45 additions and 37 deletions

View File

@ -1,5 +1,13 @@
2019-01-09 Jonathan Wakely <jwakely@redhat.com> 2019-01-09 Jonathan Wakely <jwakely@redhat.com>
* include/std/optional (_Optional_payload_base::_M_copy_assign): New
member function to perform non-trivial assignment.
(_Optional_payload_base::_M_move_assign): Likewise.
(_Optional_payload<T, true, false, true>::operator=)
(_Optional_payload<T, true, true, false>::operator=)
(_Optional_payload<T, true, false, false>::operator=): Call
_M_copy_assign and/or _M_move_assign to do non-trivial assignments.
PR libstdc++/88204 PR libstdc++/88204
* testsuite/26_numerics/complex/operators/more_constexpr.cc: Do not * testsuite/26_numerics/complex/operators/more_constexpr.cc: Do not
test std::complex<long double> if long double format is IBM128. test std::complex<long double> if long double format is IBM128.

View File

@ -157,6 +157,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Optional_payload_base& _Optional_payload_base&
operator=(_Optional_payload_base&&) = default; operator=(_Optional_payload_base&&) = default;
// used to perform non-trivial copy assignment.
constexpr void
_M_copy_assign(const _Optional_payload_base& __other)
{
if (this->_M_engaged && __other._M_engaged)
this->_M_get() = __other._M_get();
else
{
if (__other._M_engaged)
this->_M_construct(__other._M_get());
else
this->_M_reset();
}
}
// used to perform non-trivial move assignment.
constexpr void
_M_move_assign(_Optional_payload_base&& __other)
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>)
{
if (this->_M_engaged && __other._M_engaged)
this->_M_get() = std::move(__other._M_get());
else
{
if (__other._M_engaged)
this->_M_construct(std::move(__other._M_get()));
else
this->_M_reset();
}
}
struct _Empty_byte { }; struct _Empty_byte { };
template<typename _Up, bool = is_trivially_destructible_v<_Up>> template<typename _Up, bool = is_trivially_destructible_v<_Up>>
@ -286,15 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Optional_payload& _Optional_payload&
operator=(const _Optional_payload& __other) operator=(const _Optional_payload& __other)
{ {
if (this->_M_engaged && __other._M_engaged) this->_M_copy_assign(__other);
this->_M_get() = __other._M_get();
else
{
if (__other._M_engaged)
this->_M_construct(__other._M_get());
else
this->_M_reset();
}
return *this; return *this;
} }
}; };
@ -319,15 +343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(__and_v<is_nothrow_move_constructible<_Tp>, noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>) is_nothrow_move_assignable<_Tp>>)
{ {
if (this->_M_engaged && __other._M_engaged) this->_M_move_assign(std::move(__other));
this->_M_get() = std::move(__other._M_get());
else
{
if (__other._M_engaged)
this->_M_construct(std::move(__other._M_get()));
else
this->_M_reset();
}
return *this; return *this;
} }
}; };
@ -344,20 +360,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Optional_payload(const _Optional_payload&) = default; _Optional_payload(const _Optional_payload&) = default;
_Optional_payload(_Optional_payload&&) = default; _Optional_payload(_Optional_payload&&) = default;
// Non-trivial copy // Non-trivial copy assignment.
constexpr constexpr
_Optional_payload& _Optional_payload&
operator=(const _Optional_payload& __other) operator=(const _Optional_payload& __other)
{ {
if (this->_M_engaged && __other._M_engaged) this->_M_copy_assign(__other);
this->_M_get() = __other._M_get();
else
{
if (__other._M_engaged)
this->_M_construct(__other._M_get());
else
this->_M_reset();
}
return *this; return *this;
} }
@ -368,15 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept(__and_v<is_nothrow_move_constructible<_Tp>, noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>) is_nothrow_move_assignable<_Tp>>)
{ {
if (this->_M_engaged && __other._M_engaged) this->_M_move_assign(std::move(__other));
this->_M_get() = std::move(__other._M_get());
else
{
if (__other._M_engaged)
this->_M_construct(std::move(__other._M_get()));
else
this->_M_reset();
}
return *this; return *this;
} }
}; };