From cppreference.com
template<classT,classU=T>Texchange(T&obj,U&&new_value);(since C++14)
(constexpr since C++20)
(conditionally noexcept since C++23)Replaces the value of obj with new_value and returns the old value of obj.
Parameters
obj - object whose value to replace new_value - the value to assign to objType requirements -T must meet the requirements of
. Also, it must be possible to move-assign objects of type U to objects of type T. Return value
The old value of obj.
Exceptions
(none)
(until C++23)
specification:
noexcept(std::is_nothrow_move_constructible_v<T>&&std::is_nothrow_assignable_v<T&,U>)(since C++23)Possible implementation
template<classT,classU=T>constexpr// Since C++20Texchange(T&obj,U&&new_value)noexcept(// Since C++23std::is_nothrow_move_constructible<T>::value&&std::is_nothrow_assignable<T&,U>::value){Told_value=std::move(obj);obj=std::forward<U>(new_value);returnold_value;}Notes
std::exchange can be used when implementing
and, for the members that don't require
,
:
structS{intn;S(S&&other)noexcept:n{std::exchange(other.n,0)}{}S&operator=(S&&other)noexcept{n=std::exchange(other.n,0);// Move n, while leaving zero in other.n// Note: in case of self-move-assignment, n is unchanged// Also note: if n is an opaque resource handle that requires// special cleanup, the resource is leaked.return*this;}};
macroValueStdFeature
(C++14)
Example
Run this code
#include<iostream>#include<iterator>#include<utility>#include<vector>classstream{public:usingflags_type=int;public:flags_typeflags()const{returnflags_;}// Replaces flags_ by newf, and returns the old value.flags_typeflags(flags_typenewf){returnstd::exchange(flags_,newf);}private:flags_typeflags_=0;};voidf(){std::cout<<"f()";}intmain(){streams;std::cout<<s.flags()<<'\n';std::cout<<s.flags(12)<<'\n';std::cout<<s.flags()<<"\n\n";std::vector<int>v;// Since the second template parameter has a default value, it is possible// to use a braced-init-list as second argument. The expression below// is equivalent to std::exchange(v, std::vector<int>{1, 2, 3, 4});std::exchange(v,{1,2,3,4});std::copy(begin(v),end(v),std::ostream_iterator<int>(std::cout,", "));std::cout<<"\n\n";void(*fun)();// The default value of template parameter also makes possible to use a// normal function as second argument. The expression below is equivalent to// std::exchange(fun, static_cast<void(*)()>(f))std::exchange(fun,f);fun();std::cout<<"\n\nFibonacci sequence: ";for(inta{0},b{1};a<100;a=std::exchange(b,a+b))std::cout<<a<<", ";std::cout<<"...\n";}Output:
0 0 12 1, 2, 3, 4, f() Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... See also