Question

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?

Was it helpful?

Solution

When the same function template specialization can be generated from more than one declaration, the declarations are disambiguated using partial ordering of function templates as described in the C++11 standard §14.5.6.2 Partial ordering of function templates [temp.func.order]. The compiler determines which of the templates is the most specialized and prefers it.

In your example, the const T& overload of f is more specialized than the T&& overload. Intuitively, T&& can be deduced to anything that const T& can, but not vice versa, so const T& is more specific and therefore its function overload is more specialized.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top