B 14.5.5.1. The mapping of partial specializations of the template template is
If more than one relevant specialization is found, the partial order rules (14.5.5.2) are used to determine if one of the specializations is more specialized than the others. If none of the specializations is more specialized than all other relevant specializations, then using the class template is ambiguous and the program is poorly formed.
However, this only applies to your first case, when two specializations are visible, and I am not yet sure that these two specializations are valid on their own.
In your second case, however, before reaching the second specialization, the id id Unique<3>
template already exists for which (thanks to nm, Matthieu M., James Kanze) the first specialization has already been created:
14.5.5 Partial specialization of the template template
Partial specialization must be declared before the first use of a class template specialization, which would use partial specialization as a result of implicit or explicit instantiation in each translation unit in which such use occurs; no diagnostics required.
And at 14.5.5, paragraph 8
The following restrictions apply to the partial template specialization argument list:
- a partially specialized expression of a non-type of an argument should not contain a parameter of the template partial specialization, unless the argument expression is a simple identifier. [> Example:
template <int I, int J> struct A {};
template <int I> struct A<I+5, I*2> {}; // error
template <int I, int J> struct B {};
template <int I> struct B<I, I> {}; // OK
-end example]
So, it seems that non-type arguments are not involved in creating the specialization unless they are used as a simple identifier (thus Range<(value > 2)>
will be wrong).
So, it seems that your code is poorly formed.
Not directly related, but still interesting in this regard:
14.7.3 Explicit Specialization
Placing explicit specialization declarations for function templates, class templates, member functions of class templates, static data elements for class templates, member classes of class templates, member class templates for class templates, member function templates for class templates, member functions for member class template templates, member functions of member templates of classes without templates, member functional templates of member classes of class templates, etc., as well as the placement of a partial specialization of declaring class templates, member class templates in classes without templates, class templates member class templates, etc. may affect the correct formation of the program in accordance with the relative positioning of explicit declarations of specialization and their points of instantiation in the translation unit, as described above and below. When writing a specialization, be careful with its location; or there will be such a test to compile it to ignite its self-immolation.