К параметрам шаблонной функции нельзя применять никаких преобразований типа. Вместо этого при необходимости создаются новые варианты функции:
template<class T> T sqrt(t);
void f(int i, double d, complex z) { complex z1 = sqrt(i); // sqrt(int) complex z2 = sqrt(d); // sqrt(double) complex z3 = sqrt(z); // sqrt(complex) // ... }
Здесь для всех трех типов параметров будет создаваться по шаблону своя функция sqrt. Если пользователь захочет чего-нибудь иного, например вызвать sqrt(double), задавая параметр int, нужно использовать явное преобразование типа:
template<class T> T sqrt(T);
void f(int i, double d, complex z) { complex z1 = sqrt(double(i)); // sqrt(double) complex z2 = sqrt(d); // sqrt(double) complex z3 = sqrt(z); // sqrt(complex) // ... }
В этом примере по шаблону будут создаваться определения только для sqrt(double) и sqrt(complex).
Шаблонная функция может перегружаться как простой, так и шаблонной функцией того же имени. Разрешение перегрузки как шаблонных, так и обычных функций с одинаковыми именами происходит за три шага:
Эти правила слишком строгие, и, по всей видимости будут ослаблены, чтобы разрешить преобразования ссылок и указателей, а, возможно, и другие стандартные преобразования. Как обычно, при таких преобразованиях будет действовать контроль однозначности.
В любом случае, если на первом шаге найдено более одной функции, вызов считается неоднозначным и является ошибкой. Например:
template<class T> T max(T a, T b) { return a>b?a:b; };
void f(int a, int b, char c, char d) { int m1 = max(a,b); // max(int,int) char m2 = max(c,d); // max(char,char) int m3 = max(a,c); // ошибка: невозможно // создать max(int,char) }