-2

I pass rvalue std::move(x) to testForward(T&& v), but it calls print(T& t) inside.

It seems that the rvalue v has changed to an lvalue before it calls print(). I do not know why this happened. Can anyone explain it?

#include<iostream>
using namespace std;
template<typename T>
void print(T& t) {
    std::cout << "Lvalue ref" << std::endl;
}

template<typename T>
void print(T&& t) {
    std::cout << "Rvalue ref" << std::endl;
}

template<typename T>
void testForward(T&& v) {
    print(v); // call print(T& t);
}

int main(int argc, char* argv[])
{
    int x = 1;
    testForward(std::move(x)); // output: Lvalue ref
}
Useless
  • 64,155
  • 6
  • 88
  • 132

1 Answers1

5

The value category of the expression v is an lvalue, because:

... Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression

If you want to forward a forwarding reference as its original category, use std::forward, ie,

template<typename T>
void testForward(T&& v) {
    print(std::forward<T>(v));
}
Useless
  • 64,155
  • 6
  • 88
  • 132
  • Just a side note: In *given* case even `std::move` should be fine as for l-value references there's already an explicit overload, so this one should only get called on true r-value references. Still `std::forward` produces the same result anyway – and as the more general solution (correct even if the other overload doesn't exist) it should be the preferred one. – Aconcagua Oct 25 '22 at 12:57
  • Agreed, but I don't want to recommend using `std::move` with forwarding references when it'll probably confuse someone later. – Useless Oct 25 '22 at 13:09
  • Don't want to either (-> *'preferred one'*), just intended for completeness… – Aconcagua Oct 25 '22 at 13:21
  • it means even if the `v` is a right value reference type, but when it should be treated as lvalues when it passes to a function since it has name. am i right? – GuangJun Liu Oct 25 '22 at 13:31
  • It's probably clearer to use the technical terms (rvalue) than to translate them back into their notional original meaning (right value), since they've diverged significantly from where they started. And yes, the issue is that any expression consisting of a variable name is an lvalue, whatever the category of the underlying variable. – Useless Oct 26 '22 at 11:04