According to the Standard (N4659, §23.2.4, [utility.exchange]), std::exchange
should do a std::move
and a std::forward
:
template <class T, class U = T> T exchange(T& obj, U&& new_val);
Effects: Equivalent to:
T old_val = std::move(obj); obj = std::forward<U>(new_val); return old_val;
Both move
and forward
are marked as noexcept
:
(N4659, §23.2.5, [forward]):
template <class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept;
template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
Returns:
static_cast<T&&>(t)
.(...)
template <class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
Returns:
static_cast<remove_reference_t<T>&&>(t)
.
So why isn't exchange
noexcept
? Is there some other reason for this or did the committee simply overlook this? Is this being proposed or can I write one?
Unlike std::swap
, which by default only relies on move constructors and therefore should usually be noexcept
, std::exchange
may allocate resources if the new value needs to be copied. While there could probably be a complicated expression for a conditional noexcept
when new_val
is a U&&
and neither the move assignment nor the old value's move throw, it seems nobody has made such a proposal