Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is std::forward useless in this context

Tags:

c++

It has come to my attention that std::forward is useless in this context:

void consumeObject(std::unique_ptr<Object>&& robj) {
  myvector.emplace_back(std::forward<std::unique_ptr<Object>>(robj));
}

Why is that? I thought that by the time an rvalue reference binds to a function parameter (i.e. I can reference it by name) it becomes an lvalue in that scope and in order to be passed forward needs to be casted to an rvalue reference (as in perfect forwarding).

Why is it wrong/useless?

like image 506
Dean Avatar asked Nov 30 '15 13:11

Dean


1 Answers

It's not wrong to use std::forward here (per se), but it is inappropriate and thus misleading (in that sense, you could say that it is actually wrong).

The way you spell "cast something to an rvalue reference to its type" is std::move. That is the only thing that std::move does—it's a static_cast<T&&> where you don't have to spell out the T.

std::forward is a different beast, intended for use with perfect forwarding. Perfect forwarding only occurs in templates, where forwarding references are possible. A forwarding reference is a reference which, thanks to a special rule in the language, can deduce to either an lvalue reference or an rvalue reference. There, you need std::forward<T> to re-instate the appropriate value category (lvalue or rvalue).

Toy example:

void print(int &)
{
  std::cout << "Lvalue\n";
}

void print(int &&)
{
  std::cout << "Rvalue\n";
}

template <class T>
void perfectForwarder(T &&v)
{
  print(std::forward<T>(v));
}

int main()
{
  int i;
  perfectForwarder(i);
  perfectForwarder(std::move(i));
  perfectForwarder(42);
}

The output will be:

Lvalue
Rvalue
Rvalue

[Live]

like image 104
Angew is no longer proud of SO Avatar answered Oct 02 '22 15:10

Angew is no longer proud of SO