What std::exchange does, and how to remember it
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 ofy
,z
is assigned the value thatx
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
- Beautiful Pieces of Code That Print 42 for Towel Day
- (std::)Accumulate Knowledge On STL Algorithms
- How C++17 Benefits from Boost Libraries
- Out-of-line Lambdas
Share this post!