[temp.arg.explicit]/3 of the C++17 standard (final draft) says about deduction of function template arguments with explicitly specified template argument lists:
In contexts where deduction is done and fails, or [...], if a template argument list is specified and it, along with any default template arguments, identifies a single function template specialization, then the template-id is an lvalue for the function template specialization.
How does this apply to parameter packs?
Consider
template<typename...>
struct S {
S(int) {}
};
template<typename... A>
void f(S<A...>) {}
int main() {
f<int>(0);
}
This compiles on MSVC, but not on GCC and Clang, see godbolt. It would also be my intuition that it should fail, because deduction will fail, but the quote above seems to imply that even if deduction fails, since f<int>
(in my understanding) identifies uniquely a template specialization, f<int>
should be considered to refer to that specialization and then call it, without overload resolution, which will work, implicitly converting 0
to S<int>
.
What is wrong in my understanding of the quote or is MSVC indeed correct?
Note that if we try to call f<>(0);
(which I guess should work by the considerations above) all three compilers refuse to compile.
It's irrelevant. There's no such thing as a function call "without overload resolution". CWG2092 makes this clear.
[temp.over]/1 controls (broken apart for readability; emphasis mine):
When a call to the name of a function or function template is written (explicitly, or implicitly using the operator notation), template argument deduction ([temp.deduct]) and checking of any explicit template arguments ([temp.arg]) are performed for each function template to find the template argument values (if any) that can be used with that function template to instantiate a function template specialization that can be invoked with the call arguments.
For each function template, if the argument deduction and checking succeeds, the template-arguments (deduced and/or explicit) are used to synthesize the declaration of a single function template specialization which is added to the candidate functions set to be used in overload resolution.
If, for a given function template, argument deduction fails or the synthesized function template specialization would be ill-formed, no such function is added to the set of candidate functions for that template. The complete set of candidate functions includes all the synthesized declarations and all of the non-template overloaded functions of the same name. The synthesized declarations are treated like any other functions in the remainder of overload resolution, except as explicitly noted in [over.match.best].