rakeshdn
rakeshdn

Reputation: 135

What are the scenarios where assignment from std::forward is preferable over assignment from std::move ? why?

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

Answers (1)

Kerrek SB
Kerrek SB

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:

  • The argument of forward is a forwarding reference parameter of your function.
  • The argument of 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

Related Questions