Search code examples
c++language-lawyerstandards

Why is std::exchange not noexcept?


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?


Solution

  • 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