1. Changelog
- 
     R0 - 
       First submission 
 
- 
       
2. Motivation and Scope
template < class T , class U = T > constexpr T exchange ( T & obj , U && new_val ) { T old_val = std :: move ( obj ); obj = std :: forward < U > ( new_val ); return old_val ; } 
The body composes two move constructions (to build 
Such as specification would allow for a "natural" 
This is unfortunate; for instance, a primary use case of 
class buffer { int * data ; public : buffer () : data ( new int [ 42 ]) {} buffer ( buffer && other ) noexcept // at face value, this is noexcept(false)! : data ( std :: exchange ( other . data , nullptr )) {} ~ buffer () { delete [] data ; } ~~~ }; 
If one, pedantically, used a conditional 
This can, of course, be generalized to any function that features an usage of 
Note that all the operations done by 
2.1. Actual implementations
[res.on.exception.handling]/5 gives implementations some freedoms to mark
functions as 
5: An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.
At least in the case of Microsoft’s compiler toolchain, the presence of 
2.2. What about the Standard Library noexcept 
   [P1656] encodes the latest 
From a certain point of view, 
We are therefore asking for a very reasonable exception to [P1656]'s rules
in order to make 
2.3. Is this a defect fix?
We believe that the change we are proposing should be treated as a defect fix.
For this reason we are not proposing a bump in 
A prior art in this sense is [LWG2762], whose resolution is adding a
conditional 
3. Impact On The Standard
This is a pure change for 
4. Implementation experience
The proposed change has been already implemented and shipped by [MS-STL], and experimentally implemented in this libstdc++ branch on GitHub.
5. Technical Specifications
All the proposed changes are relative to [N4892].
6. Proposed wording
Modify [utility.syn] as shown:
template < class T , class U = T > constexpr T exchange ( T & obj , U && new_val ) noexcept ( see below ) ; 
Modify [utility.exchange] as shown:
template < class T , class U = T > constexpr T exchange ( T & obj , U && new_val ) noexcept ( see below ) ; Effects: Equivalent to:
Remarks: The exception specification is equivalent to:T old_val = std :: move ( obj ); obj = std :: forward < U > ( new_val ); return old_val ; is_nothrow_move_constructible_v < T > && is_nothrow_assignable_v < T & , U > 
7. Acknowledgements
Thanks to KDAB for supporting this work.
Thanks to Jonathan Wakely for the discussions on the LEWG reflector.
All remaining errors are ours and ours only.