Reputation: 210427
Why is it that optional parameters with template functions don't work in C++?
(Clarification: I'm hoping to understand why C++ was designed such that this wouldn't be possible.)
#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:
In function‘int main()’
: error: no matching function for call to‘inc(int)’
Upvotes: 2
Views: 167
Reputation: 1447
Template functions in C++ are generated at compile time, and are only generated if they are needed. So you could get a function generated like:
inc( int, int );
Which would be the T1 = int and T2 = int version. The compiler can implicitly determine the type if you pass in parameters for every template argument, so:
int a = 1;
int b = 2;
inc( a, b );
The compiler could generate a function like the one above at compile time, because it can infer that T1 = int and T2 = int. If however you do what you are doing:
inc( 5 );
The compiler can determine that T1 = int, but it cannot determine what T2 is. So no function is generated, and you get the error about the function not existing. This may be fixable if you use one template parameter:
template<class T> T inc(T v, T u = 1) { return v + u; }
Or if you provide an overload:
template<class T> T inc(T v) { return v + 1; }
There is also a third way:
inc<int, int>( 5 );
But I guess this isn't what you want...
Upvotes: 0
Reputation: 56956
Default arguments do not participate in the deduction process (only to overload resolution, and the rules are very difficult to remember -- always keep it simple).
To achieve what you want, you can provide an additional overload:
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); }
Upvotes: 1
Reputation: 1351
What Kerrek SB said is correct, the compiler just doesn't have enough to deduce T2 from (by what it's allowed to do from the standard).
In this particular case you can probably fix it by using only one template argument for everything, i.e.
template< class T > T inc( const T v, const T u = 1 ) { return v + u; }
Upvotes: 2
Reputation: 477010
You got it the wrong way round. Default arguments don't participate in argument deduction:
Argument deduction happens first, as part of selecting the desired overload, and then the default arguments of that overload are filled in if necessary.
Upvotes: 3