Если параметр шаблона функции появляется в списке параметров функции, вам не нужно указывать параметры шаблона.Например,
template<typename T>
void f(const T &t) {}
Здесь T
- это параметр шаблона, и он появляется в списке параметров функции, т.е. const T &t
.Таким образом, вам не нужно указывать параметр шаблона при вызове этой функции:
f(10); //ok
Поскольку тип из 10
равен int
, поэтому компилятор может выведите из него параметр шаблона T, и T
станет int
.
Обратите внимание, что поскольку выведение типа выполняется из информации об аргументах функции, ее называют вывод аргумента шаблона . Теперь продолжайте читать.
Если параметр шаблона не отображается в списке параметров функции, вам необходимо указать параметр шаблона.Пример:
template<typename T>
void g(const int &i) {}
Обратите внимание, g()
отличается от f()
.Теперь T
не отображается в списке параметров функции.Итак:
g(10); //error
g<double>(10); //ok
Обратите внимание, что если шаблон функции шаблонизируется и для типа возвращаемого значения, а тип возвращаемого значения отличается от типов, отображаемых в списке параметров функции, то вы должны указать тип возвращаемого значения:
template<typename T>
T h(const T &t) {}
Поскольку тип возвращаемого значения T
совпадает с параметром функции, выведение типа возможно из аргумента функции:
h(10); //ok - too obvious now
Но если вы это:
template<typename R, typename T>
R m(const T &t) {}
Затем
m(10); //error - only T can be deduced, not R
m<int>(10); //ok
Обратите внимание, что хотя шаблон функции m
шаблонизирован на два типа: R
и T
, мы предоставили только ОДИН тип при вызове,То есть мы написали m<int>(10)
вместо m<int,int>(10)
.Нет ничего плохого в том, чтобы писать позже, но это нормально, если вы этого не сделаете.Но иногда вам приходится указывать оба, даже если можно вывести один тип T
.Это когда порядок параметров типа отличается , как показано ниже:
template<typename T, typename R> //note the order : its swapped now!
R n(const T &t) {}
Теперь вы должны предоставить оба типа:
n(10); //error - R cannot be deduced!
n<int>(10); //error - R still cannot be deduced, since its the second argument!
n<int,int>(10); //ok
Новыйдело здесь: порядок параметров типа также важен .
В любом случае, это касается только элементарной концепции.Теперь я бы посоветовал вам прочитать хорошую книгу по шаблонам, чтобы узнать все продвинутые вещи, касающиеся вывода типов.