Following is the simplistic code of my problem,
void overloaded (int&& x) {
cout << "[rvalue]";
}
template <class T>
void fn (T&& x) {
overloaded(x);
}
int main() {
fn(0);
return 0;
}
I got a compile error
cannot bind ‘
int
’ lvalue to ‘int&&
’overloaded(x);
I am confused here, x
is passed as a rvalue reference into fn()
. But why the overload()
call in fn()
complains x
is a lvalue?
One, the x
argument to fn
isn't an r-value reference, it's a "universal reference" (yes, this is rather confusing).
Two, the moment you give an object a name, that name is not an r-value unless explicitly "fixed", either with std::move
(to make it an r-value reference, always), or with std::forward
(to convert it back to its original type in the case of universal references). If you want to avoid the complaint, use std::forward
to forward as the original type:
template <class T>
void fn (T&& x) {
overloaded(std::forward<T>(x));
}