Consider this code,
template
struct Sample
{
typename T::X *x; //declare pointer to T\'s X
};
In the above code, the key
C++ syntax is more crazy than that.
// typedef NOT followed by a type!
int typedef A;
// new NOT followed by a type!
new (0) int;
Others have commented about your example. The typename
specifier does not yield to lookup ignoring non-type names. So if you say new typename T::X
, and there is an object name X
in T
, it will still be found instead of the type name X
(GCC however ignores non-type names in looking up a name after a typename
. But that's not Standards compliant).
Answers to edits:
Consider this,
T::X typedef *x;
So from the context, it's still clear enough to the compiler that T::X is a type, no matter whether it appears before typedef,or after typedef.
The compiler has to know when the declaration specifiers and (i.e the "type section" and when the declarator section start (i.e the "names" section). There are declarations where the type section is empty:
// constructor definitions don't need a type section
MyClass::MyClass() { }
// conversion function definitions don't need a type section
MyClass::operator int() { }
If the first name you specify is not a type, the type section ends, and the name section starts. Saying T::X
tells the compiler:
Now I want to define
T::X
.
It reads from left to right, so it will think you forgot a semicolon when it then encounters the typedef
. Inside classes the interpretation is slightly different but much like this too. That's a simple and effective parse.
Same argument holds true for new as well.
I tend to agree with you here. Syntactically it should be unambiguous if you leave off parentheses. As I've never written a C++ parser, there may be hidden pitfalls I'm not seeing, though.
Every addition of typename
in corner cases of the language like in new
will potentially require substantial amount of design for both compilers and standards writers, while still requiring typename
for the vast majority of other cases where it's needed. I don't think that this pays off.
Then why do compilers still need the typename keyword?
Because the rules of the language are formulated in that way: every dependant name which is used in a type context must be preceeded by typename
(mutatis mutandis, the same thing holds for template name and template
keyword). Now, why the rules of the language don't make the difference between the cases where the typename is needed to remove the ambiguity and those where the context provides enough information? Probably -- I wasn't there when the decision was made -- to keep the language description to be even more complex (consider the consequences of missing cases, one way or the other).
In your example, X isn't a type name (that possibility if for compatibility with C where tag name aren't automatically type name), so you need to yuse struct
:
pX = new struct T::X;
Your code seems to go into a very gray area.
This paragraph on name hiding
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
seems to indicate that the compiler is right to complain that A::X
is not a type name.