どうやらObstacle
単なるクラスです。
驚くべきことに、以下も動作し、g ++ 4.2、g ++ 4.3、g ++ 4.4、clang ++ 2.9、およびclang++3.1でテストされています。
std::vector<Obstacle::Obstacle::Obstacle::Obstacle::Obstacle*> obstacles;
g++の複数のバージョンとclangの複数のバージョンが上記をコンパイルしました。
g ++ 4.5および4.6には、この構成に問題があります。これは、バージョン4.5以降のg++バグのように見えます。では、なぜこれが合法である必要があるのでしょうか。
これは、4.5以前のg ++、clang、および明らかに他のコンパイラのバグです。規格の関連部分は3.4.3.1、パラ1aです。
ネストされた名前指定子がクラスCを指定し、ネストされた名前指定子の後に指定された名前がCで検索されたときに、Cの注入されたクラス名である場合(9節)、その名前は代わりに次のように見なされます。クラスCのコンストラクターに名前を付けます。このようなコンストラクター名は、クラス定義の外部に表示されるコンストラクター定義のdeclarator-idでのみ使用されます。
言い換えると、Obstacle::Obstacle
クラスのコンストラクターの行外定義で使用される場合を除いて、は不正Obstacle
です。
では、これらのコンパイラはこれをどのように解析しているのでしょうか。これらのコンパイラーはObstacle::Obstacle
、コンストラクターの定義が行外の場合にのみ、特別な意味を持つものとして扱います。それ以外の場合はObstacle::Obstacle
、挿入された名前の規則に従いますが、その規則がここでは適用されないという事実を無視してください。Obstacle::Obstacle*
コンストラクターには名前がないため、コンストラクターへのポインターではありません。Obstacle::Obstacle*
代わりObstacle*
に、クラスのコンテキスト内から評価されたときに意味するものを意味しますObstacle
。ただし、クラス内には、クラスObstacle*
のインスタンスへのポインタがありますObstacle
。Obstacle::Obstacle*
、、Obstacle*
などObstacle::Obstacle::Obstacle*
です。必要な数だけ積み重ねてもObstacle
、それでもまだですObstacle*
。