Если вы попробуете max(5, 7.0)
, вы получите ошибку, даже если double
конвертируется в int
. Таким образом, специализация int
max
не участвует в разрешении перегрузки.
template <typename T>
T max(T a, T b);
template <>
int max(int a, int b);
max(5, 7.0); // compiler error (no matching function)
Однако, если бы вы использовали обычную функцию вместо специализации шаблона, вы бы получили ожидаемое поведение.
template <typename T>
T max(T a, T b);
int max(int a, int b);
max(5, 7.0); // this is fine
Когда компилятор рассматривает типы аргументов (int, double)
, он ищет функции в следующем порядке (это немного сложнее, чем в ADL и других деталях):
- точно совпадающие функции (например,
max(int, double)
. Так что max(int, int)
не будет рассматриваться на данном этапе) - сопоставление шаблонов функций (например,
max(T, U)
. Поэтому max(T, T)
не будет рассматриваться, потому что T
не может быть одновременно int
и double
) - функциями с совместимыми аргументами (например,
max(int, int)
, поскольку double
неявно преобразуется в int
)
Обратите внимание, что я не упомянул специализации шаблонов функций. Если найден соответствующий шаблон функции, будет использоваться точно соответствующая специализация (поэтому, если вы специализировались на double
s, но вы вызываете int
s, специализация не будет использоваться), в противном случае будет использоваться базовый шаблон.
Для лучшего объяснения см. cppreference .