Reputation: 72271
g++ 3.4.5 accepts this code:
template <typename T> struct A
{
static const char* const str;
};
struct B {};
typedef A<B> C;
template<> const char* const C::str = "B";
// Equivalent to following?
// template<> const char* const A<B>::str = "B";
But I'm not sure it's actually legal C++03. In particular,
[14.7p3] In an explicit specialization declaration for a class template, a member of a class template or a class member template, the name of the class that is explicitly specialized shall be a template-id.
Does this requirement say that the non-typedef version must be used at the end of this example? Or have I misinterpreted something?
Edit: Further evidence: Defect Report 403 suggests that it is incorrect to say a type (in that context, the type of an argument of a function call expression) is a template-id because template-id has a syntactic meaning, not a semantic one. Later drafts of the Standard have used "class template specialization" instead of "template-id" in 3.4.2.
This supports the argument that although A<B>
and C
represent the same type (and have identical or nearly identical semantic meaning), A<B>
is a template-id and C
is not, because the term template-id refers to the syntactic content as a sequence of tokens rather than the meaning of those tokens.
Upvotes: 4
Views: 351
Reputation: 21721
I think this is strictly ill-formed (at least according to C++ '03).
My logic is that although a typedef (7.1.3/1):
... is thus a synonym for another type.
The standard still has words to explictily allow for a typedef to be used where a class-name
is required (7.1.3/4):
A typedef-name that names a class is a class-name
There are no such words for template-id
.
Upvotes: 4
Reputation: 11761
I guess explicit specialization is not the case there. You may write the similar code without templates:
struct A
{
static const char* const str;
};
typedef A C;
const char* const C::str = "B";
This code is absolutely correct even if you use C instead of A. C is just an alias.
Just imagine how C++ code is processed. Typedefs are obviously expanded by compiler before template instantiation process is even started. The same as all comments are expanded before macros. As all macros are expanded by preprocessor before actual C++ parsing is even started. This simplifies everything.
Concerning C++03 standard, take a look at that
7.1.3/1 A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in the way described in clause 8. A typedef-name is thus a synonym for another type. A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.
I guess this paragraph explains clearly that C in your code is actually a template-id.
Upvotes: 0