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.
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.
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.