I was surprised the following code resulted in a could not deduce template argument for T
error:
struct foo { template <typename T> void bar(int a, T b = 0.0f) { } }; int main() { foo a; a.bar(5); return 0; }
Calling a.bar<float>(5)
fixes the issue. Why can't the compiler deduce the type from the default argument?
You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };
Just like in case of the function arguments, template parameters can have their default values. All template parameters with a default value have to be declared at the end of the template parameter list.
Default arguments are overwritten when the calling function provides values for them. For example, calling the function sum(10, 15, 25, 30) overwrites the values of z and w to 25 and 30 respectively.
In C++ programming, we can provide default values for function parameters. If a function with default arguments is called without passing arguments, then the default parameters are used. However, if arguments are passed while calling the function, the default arguments are ignored.
In C++03, the specification explicitly prohibits the default argument from being used to deduce a template argument (C++03 §14.8.2/17):
A template type-parameter cannot be deduced from the type of a function default argument.
In C++11, you can provide a default template argument for the function template:
template <typename T = float> void bar(int a, T b = 0.0f) { }
The default template argument is required, though. If the default template argument is not provided, the default function argument is still not usable for template argument deduction. Specifically, the following applies (C++11 14.8.2.5/5):
The non-deduced contexts are:
...
- A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
There would be some technical difficulties in achieving that in general. Remember that default arguments in templates are not instantiated until they are needed. Consider then:
template<typename T, typename U> void f(U p = T::g()); // (A) template<typename T> T f(long, int = T()); // (B) int r = f<int>(1);
This is resolved today by performing (among other things) the following steps:
In order to deduce from a default argument, that default argument would have to be itself instantiated before completing the deduction process. That could fail, leading to errors outside the SFINAE context. I.e., a candidate that may be entirely inappropriate for a call could trigger an error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With