libstdc++: Add conditional noexcept to std::exchange

This is not required by the standard, but seems useful.

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

libstdc++-v3/ChangeLog:

	* include/std/utility (exchange): Add noexcept-specifier.
	* testsuite/20_util/exchange/noexcept.cc: New test.
This commit is contained in:
Jonathan Wakely 2021-08-16 18:00:08 +01:00
parent 2db38d9fca
commit 42cfa1bd6c
2 changed files with 41 additions and 0 deletions

View File

@ -91,6 +91,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX20_CONSTEXPR
inline _Tp
exchange(_Tp& __obj, _Up&& __new_val)
noexcept(__and_<is_nothrow_move_constructible<_Tp>,
is_nothrow_assignable<_Tp&, _Up>>::value)
{ return std::__exchange(__obj, std::forward<_Up>(__new_val)); }
#if __cplusplus >= 201703L

View File

@ -0,0 +1,39 @@
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <utility>
// This is a GCC extension. std::exchange is not required to be noexcept.
static_assert( noexcept( std::exchange(std::declval<int&>(), 1) ) );
struct X
{
X(const X&);
X(X&&) noexcept;
X& operator=(const X&);
X& operator=(X&&) noexcept;
X& operator=(int);
};
extern X x, x2;
static_assert( noexcept( std::exchange(x, std::move(x2)) ) );
static_assert( ! noexcept( std::exchange(x, 1) ) );
struct Y
{
Y(Y&&) noexcept;
Y& operator=(Y&&);
};
extern Y y, y2;
static_assert( ! noexcept( std::exchange(y, std::move(y2)) ) );
struct Z
{
Z(Z&&)noexcept;
Z& operator=(Z&&) ;
};
extern Z z, z2;
static_assert( ! noexcept( std::exchange(z, std::move(z2)) ) );