Edit: after the question was edited, it now comprises two orthogonal sub-questions, which I've handled separately.
Given foo<int>(1, 2)
, should the parameter pack be deduced to cover all args?
Yes. The parameter pack does occur at the end of the parameter-declaration-list, which is the criterion for whether it's non-deduced or not. This was actually clarified in CWG issue 1569. We can convince ourselves by observing that all compilers agree this is fine:
template <typename... Args>
constexpr auto foo(Args&& ...args, ...) noexcept {
return sizeof...(args);
}
static_assert(2 == foo(1, 2), "always true");
Only when we change foo
to foo<int>
, GCC suddenly stops deducing the pack. There's no reason for it to do so, explicitly supplying template arguments to a pack should not affect whether it's eligible for deduction.
Do calls of the form (&T<...>)(...)
still invoke template argument deduction?
The answer is yes, as discussed in the open CWG issue 1038:
A related question concerns an example like
struct S {
static void g(int*) {}
static void g(long) {}
} s;
void foo() {
(&s.g)(0L);
}
Because the address occurs in a call context and not in one of the contexts mentioned in 12.3 [over.over] paragraph 1, the call expression in foo is presumably ill-formed. Contrast this with the similar example
void g1(int*) {}
void g1(long) {}
void foo1() {
(&g1)(0L);
}
This call presumably is well-formed because 12.2.2.2 [over.match.call] applies to “the address of a set of overloaded
functions.” (This was clearer in the wording prior to the resolution
of issue 704: “...in this context using &F behaves the same as using
the name F by itself.”) It's not clear that there's any reason to
treat these two cases differently.
As the note explains, prior to issue 704 we had this very explicit section:
The fourth case arises from a postfix-expression of the form &F
, where F
names a set of overloaded functions. In the
context of a function call, &F
is treated the same as the name F
by itself. Thus, (&F)(
expression-listopt )
is simply
F(
expression-listopt )
, which is discussed in 13.3.1.1.1.
The reason this wording ended up being removed is not that it was defective, but that the entire section was poorly worded. The new wording still explicitly states that overload resolution is applied to an address of an overloaded set (which is what we have here):
If the postfix-expression denotes the address of a set of overloaded functions and/or function templates, overload resolution is applied using that set as described above.
(&foo<int>)
should be done first, so cannot use later deduction... – Carrieauto p = &foo<int>;
makes both Clang and MSVC behave as one would expect. – Topazolite