# 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

Run this code

    #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, static_cast<void(*)()>(f))
       std::exchange(fun,f);
       fun();
    }

Output:

    0
    0
    12

    1, 2, 3, 4,

    f()

### See also

swap | swaps the values of two objects (function template)
atomic_exchange atomic_exchange_explicit (C++11)(C++11) | atomically replaces the value of the atomic object with non-atomic argument and returns the old value of the atomic (function template)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/utility/exchange&oldid=106226"