C++ rvalue Reference – Why Does std::move Take rvalue Reference as Argument?

c++c++11forwarding-referencemovervalue-reference

According to cppreference.com, move has signature

template< class T >
typename std::remove_reference<T>::type&& move( T&& t ) noexcept;

Why does it take a rvalue reference T&& t as its arugment?

Also when I tried the following code

void foo(int&& bar) {
    cout << "baz" << endl;
}

int main(){
    int a;
    foo(a);
}

I got an error from the compiler "an rvalue reference cannot be bound to an lvalue"

What is going on? I'm so confused.

Best Answer

It's not an rvalue reference, but a forwarding reference; which could preserve the value category of the argument. That means std::move could take both lvalue and rvalue, and convert them to rvalue unconditionally.

Forwarding references are a special kind of references that preserve the value category of a function argument, making it possible to forward it by means of std::forward. Forwarding references are either:

1) function parameter of a function template declared as rvalue reference to cv-unqualified type template parameter of that same function template:

2) auto&& except when deduced from a brace-enclosed initializer list.

On the other hand, int&& is an rvalue reference; note the difference here, if a function template parameter has type T&& with template parameter T, i.e. a deduced type T, the parameter is a forwarding reference.