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
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