Специализация шаблонов функций никогда не участвует в перегрузке: поэтому любые специализированные записи, которые вы пишете, не будут влиять на используемый шаблон, и это противоречит тому, что интуитивно ожидало бы большинство людей. В конце концов, если бы вы написали функцию nontemplate с идентичной подписью вместо специализации шаблона функции, функция nontemplate всегда была бы выбрана, потому что она всегда считалась лучшим совпадением, чем шаблон.
В книге предлагается добавить уровень косвенности путем реализации шаблона функции в терминах шаблона класса:
#include <algorithm>
template<typename T>
struct max_implementation
{
T& operator() (T& a, T& b)
{
return std::max(a, b);
}
};
template<typename T>
T& max(T& a, T& b)
{
return max_implementation<T>()(a, b);
}
Правила сопоставления параметров шаблона тонко отличаются от правил перегрузки. Пример того, что отличается, можно увидеть, когда вы пытаетесь вызвать max() с аргументами разных tyoes:
max(1,'2');
Это будет соответствовать перегруженной функции, но ни базовый шаблон, ни специализация.