Почему дополнительные параметры с шаблонными функциями не работают в C ++?
(Уточнение: я надеюсь понять Зачем C ++ был спроектирован так, что это было бы невозможно.)
#include <iostream>
template<class T1, class T2> T1 inc(T1 v, T2 u = 1) { return v + u; }
int main() { std::cout << inc(5); }
prog.cpp:
В функции‘int main()’
: ошибка: нет подходящей функции для вызова‘inc(int)’
Вы неправильно поняли. Аргументы по умолчанию не участвуют в выводе аргументов:
Аргументация вывод первый, как часть выбора желаемой перегрузки, и затем аргументы по умолчанию этой перегрузки заполняются при необходимости.
То, что Kerrek SB сказал правильно, компилятору просто не хватает для вывода T2 (из того, что ему разрешено делать из стандарта).
В этом конкретном случае вы, вероятно, можете исправить это, используя только один аргумент шаблона для всего, т.е.
template< class T > T inc( const T v, const T u = 1 ) { return v + u; }
Аргументы по умолчанию не участвуют в процессе вывода (только для разрешения перегрузки, и правила очень трудно запомнить — всегда делайте это простым).
Для достижения желаемого вы можете предоставить дополнительную перегрузку:
template <class T1, class T2> T1 inc(T1 v, T2 u) { return v + u; }
template <class T> T inc(T v) { return v + T(1); }
Шаблонные функции в C ++ генерируются во время компиляции и генерируются только в случае необходимости. Таким образом, вы можете получить функцию, сгенерированную так:
inc( int, int );
Это будет версия T1 = int и T2 = int. Компилятор может неявно определить тип, если вы передадите параметры для каждого аргумента шаблона, поэтому:
int a = 1;
int b = 2;
inc( a, b );
Компилятор может генерировать функцию, подобную приведенной выше, во время компиляции, поскольку он может сделать вывод, что T1 = int и T2 = int. Однако, если вы делаете то, что делаете:
inc( 5 );
Компилятор может определить, что T1 = int, но он не может определить, что такое T2. Таким образом, никакая функция не генерируется, и вы получаете ошибку о том, что функция не существует. Это может быть исправлено, если вы используете один параметр шаблона:
template<class T> T inc(T v, T u = 1) { return v + u; }
Или если вы предоставляете перегрузку:
template<class T> T inc(T v) { return v + 1; }
Есть и третий способ:
inc<int, int>( 5 );
Но я думаю, это не то, что вы хотите …