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.
CodePudding user response:
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.
CodePudding user response:
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;
CodePudding user response:
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;
};
template<>
struct C<bool> {
static int x;
};
//no need for template<> because the above provided epxlicit specialization declaration is not a template declaration
int C<bool>::x = 0;
In the above example, we have provided an explicit specialization for bool
. This provided definition behaves like an ordinary(non template) class. Thus, there is no need to have a prefix template<>
when defining the static data member x
outside the class because the explicitly specialized class(which is an ordinary class) is used instead of the generic class template.
Example 2
template<typename T >
struct C {
static int x;
};
template<> // needed because we have not provided an explicit specialization so that the static data member that will be generated(from C<bool) using the generic class template
int C<bool>::x = 0;
In the above example, we have not provided any explicit specialization for bool
. So we need to write the prefix template<>
because the generic class template will first be used to instantiate C<bool>
along with the static data member x
. So here the generic class template directly comes into play while instantiating the static data member while in example 1 the explicit specialization is used instead of the generic class template.