Reputation: 50548
Consider the following minimal example:
template<typename... A, typename R>
void f(A&&..., R(*)(A...)) {}
void g(int, char) {}
int main() {
f<int, char>(42, 'c', g);
}
The parameter pack A
is not the last parameter.
Anyway, I thought R
could have been deduced from the function pointer because of [temp.param]/11.
GCC (6.2) agrees with me on this, while clang (3.9) rejects the code and says that it could not infer template argument R
.
Was my expectation wrong, thus GCC shouldn't accept it, or is an issue of clang?
Upvotes: 3
Views: 161
Reputation: 6016
From that mentioned paragraph:
If a template-parameter of a class template, variable template, or alias template has a default template-argument, each subsequent template-parameter shall either have a default template-argument supplied or be a template parameter pack. If a template-parameter of a primary class template, primary variable template, or alias template is a template parameter pack, it shall be the last template-parameter. 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 ([dcl.fct]) of the function template or has a default argument ([temp.deduct]). A template parameter of a deduction guide template ([temp.deduct.guide]) that does not have a default argument shall be deducible from the parameter-type-list of the deduction guide template. [ 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 ]
In this case, template<typename... A, typename R>
can't be deduced from the parameter-type-list of function template because with:
void f(A&&..., R(*)(A...))
A&&...
is greedy, and it will consume g
as A&&
not R(*)(A...)
Speaking pedantic, as in temp.deduct.call-1:
For a function parameter pack that occurs at the end of the parameter-declaration-list, deduction is performed for each remaining argument of the call, taking the type P of the declarator-id of the function parameter pack as the corresponding function template parameter type. Each deduction deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. When a function parameter pack appears in a non-deduced context (
[temp.deduct.type]
), the type of that parameter pack is never deduced.
and as in temp.deduct.type#9:
If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list of P is compared with the corresponding argument Ai of the corresponding template argument list of A. If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context. If Pi is a pack expansion, then the pattern of Pi is compared with each remaining argument in the template argument list of A.
And it can't be specified as you can see in the third example.
clang is right when reject it.
Upvotes: 1