Проблема состоит в том, что вычитание типа шаблона должно определять точное соответствие, и в этом конкретном случае из-за ссылки в сигнатуре точное соответствие требует lvalue. Значение 42 не является lvalue, а скорее rvalue, и разрешение T
с помощью const int
не даст идеального совпадения. Поскольку вычитание типа шаблона ограничено точными совпадениями, такое удержание не допускается.
Если вместо использования литерала вы используете неизменяемое значение lvalue, то компилятор определит тип соответствующим образом, так как const int
станет идеальным соответствием для аргумента:
const int k = 10;
foo( k ); // foo<const int>( const int & ) is a perfect match
Теперь существует специальное правило, которое позволяет вызывать функцию, которая принимает константную ссылку (не изменяемое значение lvalue) со значением rvalue, что подразумевает создание временного значения lvalue, которое позднее привязывается к ссылке, но для этого правила необходимо включить функция должна иметь эту подпись перед этим, поэтому явно указывается, что тип шаблона const int
работает: foo<const int>(42)
.