Non Deduced context for a non type parameter

  • A+
Category:Languages

I am reading C++ Templates (2nd edition) and this is a snippet from the book:

template<typename... Ts, int N> void f(double (&)[N+1], Ts... ps) {return;} 

It is specified in the book that the declaration above is useless because N cannot be specified or deduced.

I am trying to understand why something like the following is an error:

double arr[2]; f<int, double, 1>(arr, 1, 2.0); 

When I compile the snippet above, I get the error that there is no matching function for call to f.

This compiles fine

template<typename... Ts, typename T>   void func(T value){};  func(1);  

even though I have an additional parameter after a parameter pack.

Why does my specifying of the template arguments explicitly not match the arguments provided? Please help me understand this.

 


The fact that N cannot be deduced has nothing to do with the parameter pack. This doesn't compile either because N cannot be deduced.

template<int N> void f(double (&)[N+1]) {}  int main() {     double arr[2];     f(arr); } 

From cppreference (Non-deduced contexts):

In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
[...]
3) A non-type template argument or an array bound in which a subexpression references a template parameter

The fact that N cannot be specified has a different cause: the standard says that you simply cannot specify a parameter placed after a parameter pack.

From [temp.param]:

A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list of the function template or has a default argument (14.8.2). [Example:

template<class T1 = int, class T2> class B;    // error  // U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { }  // error template<class... T, class U> void g() { }     // error 

—end example ]

(see this question from which I got the quote)

Your other example works because T can be deduced from the parameters.

template<typename... Ts, typename T>  void func(T value){};  func(1); // 1 is used to deduce T 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: