Following code gives compiler error which is expected (Demo):
1 template<bool> struct Range;
2
3 template<int value, typename = Range<true> > struct Unique;
4 template<int value> struct Unique<value, Range<(value > 1)> > { typedef char type[1]; };
5 template<int value> struct Unique<value, Range<(value > 2)> > { typedef char type[2]; };
6
7 Unique<3>::type o1;
8 Unique<3>::type o2;
Now, if I swap line-5 and line-7. Then there is NO compiler error !! Demo.
5 Unique<3>::type o1;
7 template<int value> struct Unique<value, Range<(value > 2)> > { typedef char type[2]; };
For o1, it’s understandable to have no error, because specialization for (value > 2) is not yet visible. But why there no error for o2 also, which sees 2 matching specializations !?
My guess is that, compiler should be choosing the Unique<3>::type with some arbitrary name when it encounters for the 1st time and then replacing Unique<3>::type everywhere with that name.
Is this a compilation bug or C++ bug or C++ “feature” ?
In 14.5.5.1 Matching of class template partial specializations, there is
However, this would only apply to your first case where there are two specializations visible, and I am not sure yet if those two specializations are valid in themselves.
In your second case, however, before the second specialization is reached, the template-id
Unique<3>already exists, for which (thanks n.m., Matthieu M., James Kanze) the first specialization is already instantiated:14.5.5 Class template partial specializations
And in 14.5.5, Item 8
So it seems that non-type arguments do not participate in specialization creation, if not used as a simple identifier (thus
Range<(value > 2)>would be wrong).So it seems your code is not well-formed.
Not directly related but still interesting in this regard:
14.7.3 Explicit specialization