Ou Changkun Ou Changkun - 3 months ago 19
C++ Question

Why rvalue reference pass as lvalue reference?

pass()
reference argument and pass it to
reference
, however a rvalue argument actually called the
reference(int&)
instead of
reference(int &&)
, here is my code snippet:

#include <iostream>
#include <utility>
void reference(int& v) {
std::cout << "lvalue" << std::endl;
}
void reference(int&& v) {
std::cout << "rvalue" << std::endl;
}
template <typename T>
void pass(T&& v) {
reference(v);
}
int main() {
std::cout << "rvalue pass:";
pass(1);

std::cout << "lvalue pass:";
int p = 1;
pass(p);

return 0;
}


the output is:

rvalue pass:lvalue
lvalue pass:lvalue


For
p
it is easy to understand according to reference collapsing rule, but why the template function pass
v
to
reference()
as lvalue?

Answer

Why the template function pass v to reference() as lvalue?

That's because v is an lvalue. Wait, what? v is an rvalue reference. The important thing is that it is a reference, and thus an lvalue. It doesn't matter that it only binds to rvalues.

If you want to keep the value category, you will have to do perfect forwarding. Perfect forwarding means that if you pass an rvalue (like in your case), the function will be called with an rvalue (instead of an lvalue):

template <typename T>
void pass(T&& v) {
    reference(std::forward<T>(v)); //forward 'v' to 'reference'
}
Comments