Я запутался с приведенным ниже поведением шаблона, где он прекрасно компилируется с пустыми угловыми скобками (шаблон без параметров), так как синтаксически, шаблон<> зарезервирован для обозначения явной специализации шаблона.
template <typename T> void add(T a, T b) { }
int main() {
add<>(10, 3); // compiles fine since both parameters are of same data type
add<>(10, 3.2); // Error: no matching function for call to add(int, double)
}
В приведенном выше случае параметр шаблона действительно необязательный?
template<>
зарезервирован для обозначения явной специализации шаблона.
Это означает разные вещи, в зависимости от контекста. Здесь это означает «использовать аргумент по умолчанию или выводимый аргумент», как если бы вы просто сказали add
,
В первом случае оба аргумента функции имеют одинаковый тип, поэтому аргумент шаблона может быть выведен как int
,
Во втором случае они имеют разные типы, поэтому аргумент шаблона не может быть выведен. Вы должны указать, что вы хотите, например, add<double>
Преобразуйте один аргумент функции, чтобы он соответствовал другому, или измените шаблон для параметризации каждого типа отдельно.
В приведенном выше случае параметр шаблона действительно необязательный?
Да, если это можно вывести из типов аргументов.
В первом случае да потому что можно сделать вывод через правила стандарта. Во-вторых, нет потому что они не могут — вы должны написать что-то вроде:
add<float>(10, 3.2);
У вас есть один параметр шаблона и два параметра функции разных типов. Вывод аргумента шаблона должен совпадать для обоих аргументов, но если вы предоставите int и double, это не сработает. Причина в том, что выводимый аргумент должен точно соответствовать преобразования типов не рассматриваются.
Синтаксис
add<double>(10, 3.2);
будет явно заставить T
быть равным double
, В этом случае int
постоянная 10
преобразуется в double
,
Вы также можете добавить еще одну перегрузку
template <typename T, typename U> void add(T a, U b) { }
и, возможно, ограничить использование SFINAE, требуя, чтобы is_convertible<T, U>