The following code:
#include <cstddef>
template <size_t N,
typename T,
T first,
T... rest>
struct A {
};
template<typename T,
T... args>
struct A<0, T, args...> {
};
int main () {
A<0, int, 1> a0;
A<2, int, 1, 2> a2;
return 0;
}
...does not compile with g++
(version 5.1.0
and 5.3.0
) due to:
error: partial specialization is not more specialized than the primary template because it replaces multiple parameters with a pack expansion
...but compiles with clang
.
Is it allowed to declare such partial specializations?
Side note: Actually, the specialization is dangerous since A<0, int>
fails to compile with both compiler (wrong number of template arguments).
gcc is correct, the code is ill-formed because the specialization isn't actually more specialized.
The rule, from [temp.class.spec] is (as a result of DR 1495, h/t T.C. for the link):
Within the argument list of a class template partial specialization, the following restrictions apply: [...] The specialization shall be more specialized than the primary template (14.5.5.2).
In order to determine that, we would rewrite the two as synthesized function templates:
template <size_t N, class T, T first, T... rest>
void __f(A<N, T, first, rest...> ); // primary
template <class T, T... args>
void __f(A<0, T, args...> ); // specialization
and then go through the partial ordering rules. That, in turn, involves synthesizing new types/values for each of the template parameters and seeing if deduction can succeed in either direction.
Definitely, the deduction of the specialization fails with the primary (due to N
vs 0
). In the other direction, from [temp.deduct.partial]:
If
A
was transformed from a function parameter pack andP
is not a parameter pack, type deduction fails.
Since we're trying to deduce T first
against a pack, deduction fails in this direction as well. This means that neither of the synthesized function templates is more specialized than other, which in turn means that the class template specialization is not more specialized than the primary template. Hence, gcc would be correct to reject.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With