Search code examples
c++c++11rvalue-reference

C++11: Why rvalue reference parameter implicitly converted to lvalue


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?


Solution

  • 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));
    }