std::exchange

From cppreference.com
< cpp‎ | utility
Defined in header <utility>
template< class T, class U = T >
T exchange( T& obj, U&& new_value );
(since C++14)
(until C++20)
template< class T, class U = T >
constexpr T exchange( T& obj, U&& new_value );
(since C++20)

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 obj
Type requirements
-
T must meet the requirements of MoveConstructible. 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)

Possible implementation

template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
    T old_value = std::move(obj);
    obj = std::forward<U>(new_value);
    return old_value;
}

Notes

This function can be used when implementing move assignment operators and move constructors:

struct S
{
  int* p;
  int n;
 
  S(S&& other)
    :p{std::exchange(other.p, nullptr)}
    ,n{std::exchange(other.n, 0)}
  {}
 
  S& operator=(S&& other) {
    p = std::exchange(other.p, nullptr); // move p, while leaving nullptr in other.p
    n = std::exchange(other.n, 0); // move n, while leaving zero in other.n
    return *this;
  }
};

Example

#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
 
class stream
{
  public:
 
   using flags_type = int;
 
  public:
 
    flags_type flags() const
    { return flags_; }
 
    ///Replaces flags_ by newf, and returns the old value.
    flags_type flags(flags_type newf)
    { return std::exchange(flags_, newf); }
 
  private:
 
    flags_type flags_ = 0;
};
 
void f() { std::cout << "f()"; }
 
int main()
{
   stream s;
 
   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, std::static_cast<void(*)()>(f))
   std::exchange(fun,f);
   fun();
}

Output:

0
0
12
 
1, 2, 3, 4, 
 
f()

See also

swaps the values of two objects
(function template)
atomically replaces the value of the atomic object with non-atomic argument and returns the old value of the atomic
(function template)
This site archives manuals. You are looking at an archived manual.
If you're looking for this specific version of this manual, you're in the right place. Otherwise, please check the version.