Используя шаблоны:
template <class T>
T GetMax (T a, T b) {
return (a>b?a:b);
}
а потом
int main () {
int i=5, j=6, k;
long l=10, m=5, n;
k=GetMax(i,j); // line 1
n=GetMax<int>(l,m); // line 2
n=GetMax<double>(l,m); // line 3
cout << k << endl;
cout << n << endl;
return 0;
}
мои вопросы:
почему я должен сделать это:
n=GetMax<int>(l,m); // line2
если я могу сделать
n=GetMax(l,m); // line 2
а почему это компилируется?
n=GetMax<double>(l,m);
когда L а также м целые числа, которые сильно отличаются от двойных?
В этом контексте вы можете думать, что создание шаблона является простой заменой текста (это не так уж и далеко), то есть, когда вы выяснили параметры шаблона. Так:
T
считается int
, Вы можете найти точную логику ранжирования соответствующих параметров шаблона в стандарте. Ваш случай довольно прост. После определения параметра шаблона выполняется подстановка, поэтому ваша функция выглядит следующим образом:
int GetMax (int a, int b) {
return (a>b?a:b);
}
Он компилируется, когда вы используете несколько параметров и имеете много возможных совпадений с наследованием и т. Д. И т. Д.
В вашем случае вы можете вызвать равные совпадения, используя два разных типа для параметров, т.е. GetMax(i,l)
, T
имеет двух кандидатов: double
как int
и оба одинаково хороши.
Это связано со знаменитым SFINAE (ошибка замены не является ошибкой). Компилятор пытается сгенерировать версии для возможных комбинаций параметров, и в случае неудачи он не учитывается для окончательного ранжирования. В вашем случае две замены прошли успешно.
Вы прямо заявляете, что T int
, Таким образом, компилятор не вызывает автоматического сопоставления параметров. Созданная версия выглядит так же, как 1.
Вы прямо заявляете, что T в double
, Опять же, компилятор не вызывает никакой логики относительно типов.
Слепо генерирует версию для double
и использует это:
double GetMax (double a, double b) {
return (a>b?a:b);
}
Это законно, чтобы передать int
к функции, использующей double
происходит неявное преобразование.
Это совершенно законно:
void f(double d) {};
int main(){
int i = 5;
f(i);
}
Нижняя линия:
Выяснение типов шаблонов — это не просто логика, а вызов функции. Думайте об этом как об отдельных фазах. Вывод типа разработан, чтобы иметь смысл для вызова, но это отдельная вещь.
Вы можете опустить типы в шаблонных функциях, потому что они вычитаются во время компиляции
И второй вопрос, нет ошибки, потому что целые числа изящно отступают в два раза, поэтому они будут преобразованы и использованы как двойные в логике вашего шаблона.