0

まず、私のコードはコンパイルされ、コンパイラを搭載したMacOSXで正常に実行されます

i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1

しかし、コンパイラを備えたUbuntuでは

g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

コンパイルされません。

私のヘッダーには

std::vector<Obstacle::Obstacle*> obstacles;

これにより、Ubuntuで次のコンパイルエラーが発生します。

error: ‘Obstacle::Obstacle’ cannot appear in a constant-expression

それを機能させるために何を変更する必要があるかについてのアイデアはありますか?OS Xと同じように機能させるために、Ubuntuで使用する必要のある魔法のコンパイルフラグはありますか?

ありがとうございました

編集:Obstacleクラスです。

4

2 に答える 2

4

どうやら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*のインスタンスへのポインタがありますObstacleObstacle::Obstacle*、、Obstacle*などObstacle::Obstacle::Obstacle*です。必要な数だけ積み重ねてもObstacle、それでもまだですObstacle*

于 2012-10-14T15:42:36.440 に答える
1

コンストラクターポインタをストアドタイプとして渡すことはできません。

それ以外の

std::vector<Obstacle::Obstacle*> obstacles;

試す

std::vector<Obstacle*> obstacles;
于 2012-10-14T15:15:35.717 に答える