В следующем коде у меня есть функция шаблона не-члена и ее полная специализация для типа int
.
#include <iostream>
template <typename U>
void f(const U& x, const U& y)
{
std::cout << "generic " << x << " " << y << std::endl;
}
template <>
void f(const int& x, const int& y)
{
std::cout << "specialization int " << x << " " << y << std::endl;
}
int main()
{
int a = 1;
f(a, a);
f('a', 'a');
f('a', 1); // Compiler error
// f<int>('a', 1); // This compiles
return 0;
}
Хотя на языке доступно неявное преобразование из char
в int
, компилятор (g ++ 7.3.0 и clang 6.0.1) не компилирует код, выдавая ошибку
error: no matching function for call to ‘f(char, int)’
deduced conflicting types for parameter ‘const U’ (‘char’ and ‘int’)
Хотя понятно, почему вывод шаблона не будет работать, мне неясно, почему компилятор не учитывает неявное преобразование после того, как он отбросил общий шаблон. Например, если я явно создаю экземпляр f
с U=int
, раскомментируя соответствующую строку в коде как
f<int>('a', 1);
затем код компилируется и правильно выдает вывод
specialization int 1 1
generic a a
specialization int 97 1
Если вместо этого я дополню код перегрузкой из f
вместо специализации шаблона как
#include <iostream>
template <typename U>
void f(const U& x, const U& y)
{
std::cout << "generic " << x << " " << y << std::endl;
}
void f(const int& x, const int& y)
{
std::cout << "overload int " << x << " " << y << std::endl;
}
int main()
{
int a = 1;
f(a, a);
f('a', 'a');
f('a', 1);
return 0;
}
Затем код компилируется и выдает ожидаемый результат
overload int 1 1
generic a a
overload int 97 1
В итоге: почему неявные преобразования работают для перегрузки, а не для, казалось бы, эквивалентной специализации шаблона?