For this code (available at http://ideone.com/Mo7fQr)
template<typename T>
void f(const T&) { std::cout << "const T& overload\n"; }
template<typename T>
void f(T&&) { std::cout << "T&& overload\n"; }
int main()
{
const int x = 0;
f(x); // calls const T& overload
f(std::move(x)); // calls T&& overload
}
the first call to f
(with an lvalue) calls the const T&
overload, while the second call (with an rvalue) calls the T&&
overload. At least that's what happens with gcc 4.8.1 and the most recent VC++ (VC12).
I think I understand why the second call resolves as it does: because the first template instantiates to taking a const int&
parameter, while the second template instantiates to taking a const int&&
parameter, and because the argument passed at the call site is an rvalue, it preferentially binds to the rvalue reference. (I believe this is specified in the C++11 standard at 13.3.3.2/3 bullet 1 sub-bullet 4.)
But for the first call to f
, both templates instantiate to taking a parameter of type const int&
. So why is the first template preferred when a const
lvalue is passed in?