Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the compiler deduce the template type from default arguments?

Tags:

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?

like image 854
Samaursa Avatar asked Mar 09 '12 04:03

Samaursa


People also ask

CAN default arguments be used with the template?

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 { };

Can template parameters have default values?

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.

What is the use of default arguments explain with the help of an example?

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.

Does C++ support default arguments?

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.


2 Answers

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.
like image 125
James McNellis Avatar answered Oct 20 '22 17:10

James McNellis


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:

  1. attempt to deduce template parameters for candidates (A) and (B); this fails for (A), which is therefore eliminated.
  2. perform overload resolution; (B) is selected
  3. form the call, instantiating the default argument

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.

like image 25
Daveed V. Avatar answered Oct 20 '22 17:10

Daveed V.