user12002570
user12002570

Reputation: 1

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.

Upvotes: 0

Views: 87

Answers (3)

user12002570
user12002570

Reputation: 1

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.

Upvotes: 0

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38539

The first

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

// This is the template specialisation for bool and all struct members
template<> 
struct C<bool> {
    static int x;
};

// This is the extraneous template specialisation for bool
// and the single struct member, already specialized above - error
// template<> 
// int C<bool>::x = 0;

The modified first example

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

// This is the template specialisation for bool and the single struct member
template<> 
int C<bool>::x = 0;

// This is the extraneous template specialisation for bool
// and all struct members, one of them is already specialized above - error
// template<> 
// struct C<bool> {
//    static int x;
// };

The second

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

// This is the unique template specialisation for bool - ok
template<>
int C<bool>::x = 0;

Another example

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

// This is the template specialisation for bool
template<> 
struct C<bool> {
    static int x;
};

// This is another template socialisation for int - ok
template<>
int C<int>::x = 0;

Upvotes: 1

molbdnilo
molbdnilo

Reputation: 66371

They aren't different syntaxes for the same thing, they are different syntaxes for different things.

The first specializes the entire struct, including all its members.
That is, the specialization C<bool>::x is already implied by the struct specialization, and you're not allowed to specialize twice.
int C<bool>::x = 0; is a regular definition of the static member in that specialization.

The second only specializes the member, not the struct, and defines it at the same time.

Upvotes: 2

Related Questions