I don't get the reason for which a parameter pack must be at the end of the parameter list if the latter is bound to a class, while the constraint is relaxed if the parameter list is part of a member method declaration.
In other terms, this one compiles:
class C {
template<typename T, typename... Args, typename S>
void fn() { }
};
The following one does not:
template<typename T, typename... Args, typename S>
class C { };
Why is the first case considered right and the second one is not?
I mean, if it's legal syntax, shouldn't it be in both the cases?
To be clear, the real problem is that I was defining a class similar to the following one:
template<typename T, typename... Args, typename Allocator>
class C { };
Having the allocator type as the last type would be appreciated, but I can work around it somehow (anyway, if you have a suggestion it's appreciated, maybe yours are far more elegant than mine!!).
That said, I got the error:
parameter pack 'Args' must be at the end of the template parameter list
So, I was just curious to fully understand why it's accepted in some cases, but it is not in some others.
Here is a similar question, but it simply explains how to solve the problem and that was quite clear to me.
It is valid for function templates but only when argument deduction can help the compiler resolve the template parameters, as it stands your function template example is virtually useless because
the compiler has no way of determining which template parameters belong to the parameter pack, and which to
S
. In fact as @T.C. points out it should actually be a syntax error because a function template defined in this manner cannot ever be instantiated.A more useful function template would be something like
as now the compiler is able to unambiguously match the function parameter
s
with the template typeS
, with the side effect thatS
will always be deduced - all explicit template parameters after the first will belong toArgs
.None of this works for (primary) class templates, parameters aren't deduced and it's expressly forbidden:
From draft n4567
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4567.pdf
[temp.param] / 11
(if they were deduced it would be ambiguous as in the function template example).
The first one is not right. The compiler is just buggy and failed to diagnose it. [temp.param]/11:
If the function type
T(Args...)
is meaningful to the end-user, one way to fix this would be to use a partial specialization instead:Depending on the actual requirements, type-erasing the allocator might also be worth considering.