Вывод аргументов шаблона
Обычная функция double max_of(double a, double b) принимает вызов max_of(1, 2.5): аргумент 1 преобразуется в double. Шаблон с тем же телом этот вызов отвергает:
#include <iostream>
template <typename T>
T max_of(T a, T b) {
return a > b ? a : b;
}
int main() {
std::cout << max_of(1, 2.5) << '\n'; // ✗
}error: no matching function for call to 'max_of'Вывод из аргументов
В вызове шаблона тип T обычно не пишут: компилятор находит его сам. Это вывод аргументов шаблона (template argument deduction): компилятор сравнивает тип каждого аргумента с типом его параметра. Литерал 3 имеет тип int, поэтому для max_of(3, 7) получается T = int:
std::cout << max_of(3, 7) << ' ' << max_of(2.5, 1.5) << '\n'; // 7 2.5Сначала компилятор выводит T, а потом инстанцирует функцию для этого типа. Выведенный тип подставляется везде, где в шаблоне стоит T, в том числе в тип результата: max_of(2.5, 1.5) возвращает double.
Каждый аргумент выводит T независимо от остальных, и результаты должны совпасть. В max_of(1, 2.5) первый аргумент даёт int, а второй — double. Преобразования вроде int → double при выводе не применяются, поэтому выбрать один тип компилятор не может. Об этом говорит пояснение под ошибкой: deduced conflicting types for parameter 'T' ('int' vs. 'double').
Явный аргумент шаблона
Тип можно указать самому — в угловых скобках после имени шаблона. Такой явный аргумент шаблона (explicit template argument) заменяет вывод: T уже известен, и аргументы преобразуются, как при вызове обычной функции. Другой способ — передать аргументы одного типа: литерал 1.0 имеет тип double.
std::cout << max_of<double>(1, 2.5) << ' ' << max_of(1.0, 2.5) << '\n'; // 2.5 2.5Явный аргумент нужен и тогда, когда тип аргумента не выбрать самому. Вызов max_of(s.size(), 10) для строки s не скомпилируется: size() возвращает std::size_t, а 10 имеет тип int. Вызов max_of<std::size_t>(s.size(), 10) компилируется и возвращает большее из двух чисел.
Частая ошибка
Параметр T встречается только в типе результата, и тип ждут от переменной, которая получает результат:
template <typename T>
T zero() {
return T{};
}
int main() {
double d = zero(); // ✗
}error: no matching function for call to 'zero'Запись T{} создаёт значение типа T по умолчанию, как int x{}: для чисел это 0. Но у zero() нет аргументов, а тип переменной d в выводе не участвует. Поэтому компилятор поясняет: couldn't infer template argument 'T'. Укажите тип явно: zero<double>().