Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non Deduced context for a non type parameter

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.

like image 902
MSS Avatar asked Dec 15 '18 07:12

MSS


1 Answers

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
like image 72
Nelfeal Avatar answered Sep 19 '22 14:09

Nelfeal