Reputation: 135
While learning about std::exchange
on cppreference.com , I came across its "possible implementation" which is pasted below.
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;
}
It looked a bit odd to see obj = std::forward
in an assignment statement instead instead of std::move
, which I think would have the same effect.
My understanding is that std::move
is equivalent to a static_cast
to rvalue reference type (but more expressive) and returns an xvalue always, whereas std::forward
returns the same value type it is passed.
My question is why is std:forward
used in above snippet? and is there an easy rule of thumb to decide when this is the better choice?
Upvotes: 2
Views: 391
Reputation: 477060
The fact that there's assignment is irrelevant. What distinguishes forward from move is what kind of argument they take when used inside your function:
forward
is a forwarding reference parameter of your function.move
is an rvalue reference parameter of your function (or more generally, anything you know to have no further aliases).If you exchange
with an lvalue, you don't want that to be moved-from!
For example, consider:
std::vector<int> a, b;
f(std::exchange(a, b));
This effectively calls f(a)
but also performs a = b;
. It does not perform a = std::move(b)
; b
is still usable in its original form afterwards!
See also this answer of mine, as well as many other related answers like What is std::move(), and when should it be used?, What's the difference between std::move and std::forward, and links therein.
Upvotes: 5