Andrey Lyubimov
Andrey Lyubimov

Reputation: 673

Confusion with universal references

I have this code:

void f2(int& lvalue)
{
  std::cout <<"lvalue\n";
}
void f2(int&& rvalue)
{
  std::cout << "rvalue\n";
}

template<typename T>
void f(T&& param)
{
  f2(param);
}

I expect to get "lvalue" if I call f with:

int v = 10;
f(v);

and expect "rvalue" if I call f with:

f(10);

However, I always get the lvalue case. Please, can anybody explain where I'm wrong.

Upvotes: 3

Views: 131

Answers (1)

TartanLlama
TartanLlama

Reputation: 65620

You need to forward your parameter. Although the type of param could be an rvalue reference, param itself is still an lvalue.

f2(std::forward<T>(param));

std::forward ensures that param gets the same reference qualifier as the argument which was passed. This is known as perfect-forwarding.

If you call f(10):

  • param is an lvalue
  • std::move(param) is an rvalue
  • std::forward<T>(param) in an rvalue

If you call f(v):

  • param is an lvalue
  • std::move(param) is an rvalue
  • std::forward<T>(param) in an lvalue

Upvotes: 9

Related Questions