I've looked into this exact question myself and I've found it surprisingly difficult to get a clear answer. As best I can tell, f1(1)
should be rejected but f2(1)
should be accepted.
That said:
- clang++-5.0 accepts both
- g++-6 accepts both
- EDG 4.14 rejects both
As you pointed out, a function parameter pack that does not occur at the end of the list is a non-deduced context ([temp.deduct.type] p5):
The non-deduced contexts are:
- ...
- A function parameter pack that does not occur at the end of the parameter-declaration-list.
and [temp.deduct.call] p1 (amended via CWG 1388) clarifies that such a parameter pack is never deduced.
When a function parameter pack appears in a non-deduced context, the type of that parameter pack is never deduced.
Additionally, [temp.arg.explicit] p3 specifies:
A trailing template parameter pack (14.5.3) not
otherwise deduced will be deduced to an empty sequence of template arguments.
so, taking this into account for the f2(1)
call: the pack T is a trailing template parameter pack (although it is not a trailing function parameter pack), so it deduced to an empty pack and the call is valid.
However, for f1(1)
, the pack T is also not a trailing template parameter pack because it is followed by U
, so it is not assumed to be an empty pack per [temp.arg.explicit] p3. Therefore, since the template paramter pack T cannot be deduced for the call to f1(1)
, it should not take part in overload resolution and the call should fail.
Note that several similar questions/examples have been brought up in other discussions, but that they are all subtly different:
- The
f(0)
call in the example code of CWG 1388 and CWG 1399 is valid because the pack in question is a trailing template parameter pack, so it falls into the case I mentioned above. Here is the code from CWG 1399:
template <class... T>
void f(T..., int, T...) { }
int main() {
f(0); // OK
f<int>(0,0,0); // OK
f(0,0,0); // error
}
- The example code in the discussion of LLVM bug 21774 is similar to the CWG 1399 example, the pack is a trailing template parameter pack. Likewise for this question.
- CWG 2055, which is unresolved, touches upon a similar test case. Whenever that gets resolved, its resolution will likely shed some light as to the proper behavior of the examples in this question. Here is the issue mentioned in CWG 2055:
It is not clear that [the current wording of the standard] permits an example like:
template<typename... T> void f(typename T::type...) {
}
int main() {
f<>();
}