Jonathan Boccara's blog

What std::exchange does, and how to remember it

Published September 18, 2020 - 0 Comments

std::exchange was introduced in the C++ standard library in C++14 under the header <utility>.

Its name suggests that it’s a general-purpose and useful function, and its template prototype working with any type confirms this impression.

I don’t know about you, but I always had a problem with std::exchange: I couldn’t remember what it was doing. I learnt several times the operations that std::exchange performs, but each time I forgot them soon after.

Then at some point it clicked: std::exchange is a setter returning the old value. Ignoring the name “exchange” but thinking of it as a “setter” helped me make it stick to my mind.

It might just be me having a hard time with std::exchange for some reason. But just in case you also have issues remembering the operations of std::exchange, let’s see why std::exchange has this meaning, and why this meaning is not obvious from its name.

This should help you remember it once and for all.

What std::exchange does

Let’s get down to the operations std::exchange performs. Consider the following code:

int z = std::exchange(x, y);

After this line of code executes:

  • x is assigned the value of y,
  • z is assigned the value that x had initially.

This definition is pretty straightforward. But after some time, I just couldn’t remember which value std::exchange assigns to which.

A setter

The job of a setter in a class is to assign the value it receives to one of a data members of the class. Here is the typical implantation of a setter:

class X
{
public:
    void setX(int y)
    {
        x = y;
    }
private:
    int x;
};

There is an (old) programming convention that suggested to make the setter return the old value:

class X
{
public:
    int setX(int y)
    {
        int oldX = std::move(x);
        x = y;
        return oldX;
    }
private:
    int x;
};

This is by the way not a good practice for classes because the setter now has two responsibilities: getting and setting the value. This leads to confusing calling code.

Let’s now transpose this concept to a free functions assigning to a local object:

setX(x, y);

setX does the same thing as operator=: it assigns y to x. Let’s now implement the old conventions for classes to this function, to make it return the old value of x:

int z = setX(x, y);

std::exchange is like the setX of this example.

Why std::exchange is confusing

Despite its very simple meaning, I think std::exchange can be hard to remember because of its name.

To me, “exchange” sounds like two parties exchanging something: one receives what the other gives it. With this meaning, std::exchange sounds very close to std::swap. But in reality std::exchange does something very different from std::swap.

If we think of std::exchange as it if was named std::set or std::setAndGetOldValue, it is clear that it has nothing to do with std::swap and its meaning becomes obvious, and easy to remember.

How std::exchange can make code more concise

Now that we’re clear on std::exchange, the next step is to see where to use it.

The next post will be a guest post written by Ben Deane, where he’ll show us how to use std::exchange to make code concise and expressive. Stay tuned!

You will also like

Don't want to miss out ? Follow:   twitterlinkedinrss
Share this post!Facebooktwitterlinkedin