Почему значения const l связываются иначе, чем значения const r, заданные T&& и const T& overloads?

Для этого кода (доступно на 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
}

первый звонок f (с lvalue) вызывает const T& перегрузка, в то время как второй вызов (с rvalue) вызывает T&& перегрузки. По крайней мере, так происходит с gcc 4.8.1 и самой последней версией VC++ (VC12).

Я думаю, я понимаю, почему второй вызов разрешается так, как он делает: потому что первый шаблон создает экземпляр const int& параметр, в то время как второй шаблон создает экземпляр const int&& параметр, и поскольку аргумент, передаваемый на сайте вызова, является rvalue, он предпочтительно привязывается к ссылке на rvalue. (Я полагаю, что это указано в стандарте C++11 в п. 1 пункта 13.3.3.2/3).

Но для первого звонка fоба шаблона создают экземпляр типа const int&, Так почему первый шаблон предпочтительнее, когда const Значение передается в?

1 ответ

Решение

Когда одна и та же специализация шаблона функции может быть сгенерирована из более чем одного объявления, объявления устраняются с помощью частичного упорядочения шаблонов функций, как описано в стандарте C++11 §14.5.6.2 Частичное упорядочение шаблонов функций [temp.func.order], Компилятор определяет, какой из шаблонов является наиболее специализированным, и предпочитает его.

В вашем примере const T& перегрузка f является более специализированным, чем T&& перегрузки. Наглядно, T&& может быть выведено на все, что const T& может, но не наоборот, так const T& является более конкретным, и поэтому его перегрузка функции является более специализированной.

Другие вопросы по тегам