Dan Nissenbaum
Dan Nissenbaum

Reputation: 13908

Should changing the order of template parameters in the "template<...>" line for a specialization result in a duplicate definition, or ambiguity?

I have a question related to Edge-case: When (only) reversing order of template parameters in specialization, can non-specialized version ever be reached?.

This is a theoretical question involving code that would probably considered to be poorly written. However, I want to thoroughly understand template syntax.

Suppose two template specializations differ only in the order of template parameters within the template<...> line, as follows:

#include <iostream>

// Primary template
template<typename T1, typename T2, typename T3>
class A
{};

// Specialization #1
template<typename T2, typename T3>
class A<int, T2, T3>
{};

// Specialization #2
// Differs only in order of parameters in the "template<...>" line
template<typename T3, typename T2>
class A<int, T2, T3>
{};

int main()
{
    A<int, int, int> a; // <-- Compiler error: Ambiguous template specializations
    return 0;
}

In the Visual Studio 2010 compiler, the error involves the ambiguous template specialization: 'A<T1,T2,T3>' : more than one partial specialization matches the template argument list. could be 'A<int,T2,T3>' or 'A<int,T2,T3>'.

In particular, the error is not 'A<int,T2,T3>' : class template has already been defined, which is the error produced when the second specialization is character-for-character identical to the first (i.e., the order of template parameters is not reversed, and reads template<typename T2, typename T3>, just as in specialization #1).

I think, however, that the order of parameters listed in the template<...> line within a template specialization makes no difference. Specifically, I think that the purpose of the template<...> line in a specialization is only to identify the tokens that appear in the specialized type name (A<int, T2, T3>) as syntactically valid template parameters, and not typos. According to this reasoning, the order of parameters in the template<...> line for a template specialization should make no difference, and two template specializations that differ character-for-character only in the order of these parameters should be considered duplicate definitions, rather than ambiguous specializations.

If I am correct, than the Visual Studio 2010 compiler is correct in that it reports an error in this case, but incorrect in that it identifies the error as an ambiguous specialization, rather than as a multiply defined specialization.

Am I correct? Does the order of template parameters in the template<...> line of a template specialization make no difference, such that two template specializations which are identical otherwise character-for-character should be considered redundant definitions of the same template specialization, rather than two different, but ambiguous, template specializations?

If I am incorrect, than it must be that indeed the two specializations in the code above are different (i.e., not multiply defined). If so, can someone please explain why they are different and how this difference might be demonstrated by client code?

Upvotes: 1

Views: 430

Answers (1)

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507105

The identity of a partial specialization is its argument list passed to its template. Template type parameter names denote specific dependent types, whose identity includes their position in their template parameter list and the nesting depth of their template parameter list (i.e. a member template's list is one more level nested than its enclosing template if the member template is a member of a class template).

This makes sense because you need to mangle two function templates different that overload each other and differ only in their template parameter order. Their instantiation behavior is different because their position directly correspond to the respective argument in a function template calls' template argument list.

If you reorder their the positions, the argument lists become different because different types are passed as arguments. So you are not redefining partial specializations.

Upvotes: 1

Related Questions