Apparently Obstacle
is just a class.
Amazingly, the following also works, tested in g++ 4.2, g++ 4.3, g++ 4.4, clang++ 2.9, and clang++ 3.1:
std::vector<Obstacle::Obstacle::Obstacle::Obstacle::Obstacle*> obstacles;
Multiple versions of g++ and multiple versions of clang compiled the above.
g++ 4.5 and 4.6 have problems with this construct. This looks like a g++ bug, versions 4.5 and higher. So why should this be legal?
This is a bug in pre 4.5 g++, clang, and apparently other compilers. The relevant portion of the standard is 3.4.3.1, para 1a:
If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition that appears outside of the class definition.
In other words, Obstacle::Obstacle
is illegal except when used in an out of line definition of a constructor for class Obstacle
.
So how are these compilers parsing this? Those compilers are treating Obstacle::Obstacle
as having special meaning only in the case of an out of line definition of a constructor. Otherwise, Obstacle::Obstacle
follows the injected name rules, but ignore the fact that that rule does not apply here. Obstacle::Obstacle*
isn't a pointer to the constructor because constructors don't have names. Obstacle::Obstacle*
instead means whatever Obstacle*
means when evaluated from within the context of the class Obstacle
. But inside the class, Obstacle*
is still a pointer to an instance of class Obstacle
. Obstacle::Obstacle*
is just an Obstacle*
, as is Obstacle::Obstacle::Obstacle*
, and so on. Pile on as many Obstacle
s you want and it's still just an Obstacle*
.