Search code examples
c++templatestemplate-specializationclass-templateexplicit-specialization

What is the need for having two different syntaxes for specializing data member of a class template


I was writing an example involving specialization of class template where I noticed that the standard allows two different syntax for specialization of a data member as shown below:

template<typename T >
struct C {
    static int x;
};
template<> 
struct C<bool> {
    static int x;
};
//here we cannot write prefix template<> 
int C<bool>::x = 0;

As can be seen in the above example, we are not allowed to write the prefix template<> for defining the static data member x. And i understand this and have no problem with the above example. But when i modified the example to look like as shown below, i was surprised to see that we are allowed/required to write the prefix template for defining the static data member x:

template<typename T >
struct C {
    static int x;
};

template<>  //here why is the use of prefix template<> allowed/required? Why standard mandates that we cannot omit this prefix template<> here but in the previous example we can omit it
int C<bool>::x = 0;

As can be seen in the above modified example, we are required to use the prefix template<> for defining the same static data member x. My question is that why is there a difference in syntax for defining the same data member x in the above two examples. That is why the standard requires the use of prefix template<> in the second example. Why can't we omit that prefix in the second example just like first example. Does using the prefix template<> in the second example help solve some problem(like some ambiguity or something else).

PS: Note that my question is not about which statement from the standard allows this usage(since i already know using the below given quoted statement from cppreference) but about the rationale for allowing these two syntaxes(one that uses template<> and one that doesn't).


I also came across the following and the code example given in the mentioned link that explain how this is allowed:

When defining a member of an explicitly specialized class template outside the body of the class, the syntax template<> is not used, except if it's a member of an explicitly specialized member class template, which is specialized as a class template, because otherwise, the syntax would require such definition to begin with template required by the nested template .

The above quoted statement explains along with the example given there explains how the standard allows the above given examples in my question. But i am looking for a reason why is the prefix template<> mandated by the standard in the second example. Why standard doesn't allow the ommision of prefix template<> in the second example as in example 1.


Solution

  • Explicit specialization declaration of a class template is not a template declaration. [Source]. This means that when we provide an explicit specialization for a class template, it behaves like an ordinary class.

    Now we can apply this to the examples given in question.

    Example 1

    template<typename T >
    struct C {
        static int x;
    };
    //this is an specialization and so we must use template<> prefix
    template<> 
    struct C<bool> {
        static int x;
    };
    //this is just ordinary out of class definition of data member `x`. That is, this is not a specialization and so we don't need the prefix template<>
    int C<bool>::x = 0;
    
    

    In the above example, first we have provided an explicit specialization for bool of the class template C itself which behaves like an ordinary class(in the sense that it is not a template declaration). The template<> prefix is needed here because we were providing a specialization. Next, we provide an ordinary out-of-class definition of the static data member x of the specialization that we provided. But here we don't need the template<> prefix because this is not a specialization. This is just an ordinary out-of-class definition of a static data member.

    Example 2

    template<typename T >
    struct C {
        static int x;
    };
    
    template<>  // needed because this is not an ordinary out-of-class definition of data member x. Instead this is a specialization 
    int C<bool>::x = 0;
    
    

    In the above example, we have not provided any explicit specialization for class template C. Instead we are directly providing a specialization for the static data member x. This means that unlike example 1, here we are not providing an out-of-class definition of a static data member but instead we're providing a specialization. So in this case we need the template<> prefix.

    TLDR

    In example 1 int C<bool>::x = 0; is just an ordinary out-of-class definition of a static data member x and not a specialization, so we don't need the prefix template<> for this. Conversely, in example 2 template<> int C<bool>::x = 0; is a specialization of a static data member x and not an ordinary out-of-class definition. So in this case(example 2) the prefix template<> is needed.