Для этого кода (доступно на 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
Значение передается в?
Когда одна и та же специализация шаблона функции может быть сгенерирована из более чем одного объявления, объявления устраняются с помощью частичное упорядочение шаблонов функций как описано в стандарте C ++ 11 §14.5.6.2 Частичное упорядочение шаблонов функций [temp.func.order]. Компилятор определяет, какой из шаблонов является наиболее специализированным, и предпочитает его.
В вашем примере const T&
перегрузка f
является более специализированным, чем T&&
перегрузки. Наглядно, T&&
может быть выведено на все, что const T&
может, но не наоборот, так const T&
является более конкретным, и поэтому его перегрузка функции является более специализированной.
Других решений пока нет …