0

私は次のようなベクトルクラスを持っています:

class Vector3
{

 public:
   Vector3(){m_x = m_y = m_z = 0.0f;}
   Vector3(const float & i_x, const float & i_y, const float & i_z):
     m_x(i_x), 
     m_y(i_y),
     m_z(i_z)
     {}

   Vector3 operator+(const Vector3 & i_other);
private:
   float m_x;
   float m_y;
   float m_z;
};

Vector3::Vector3 Vector3::operator+(const Vector3 & i_other)
{
   float tx = m_x + i_other.m_x;
   float ty = m_y + i_other.m_y;
   float tz = m_z + i_other.m_z;
   return Vector3(tx, ty, tz);
}

明らかに、戻り型が。ではなく、でVector3::operator+あるため、synaxの定義は間違っています。名前空間があり、名前空間内にクラスがあることを意味します。しかし、私にはクラスしかなく、ここには名前空間はありません。Vector3::Vector3Vector3Vector3::Vector3Vector3Vector3Vector3

私の質問は、Ubuntu 12.04では、上記の構文をコンパイルできないことです(Ubuntuのg ++​​コンパイラは[gccバージョン4.6.3]です)。ただし、Macでは、g ++はコードをコンパイルできます(Macのg ++​​コンパイラは[gccバージョン4.2.1]です)。また、この構文をRed Hat Linuxマシンでテストしましたが、機能します(g ++バージョンは[gccバージョン4.4.6]です)

それで、gccの異なるバージョンは異なるコンパイル原理を持っていますか?または、Ubuntuのg ++​​が壊れましたか?

4

1 に答える 1

2

古いコンパイラは正しくありません。少し驚きました。

おそらくVector3::Vector3、注入されたタイプ名として解析されています。のスコープ内でclass Vector3 { }は、識別子Vector3はコンストラクターではなくクラスを参照します(もちろん、コンストラクターを宣言する場合を除く)。そして、一見すると、§3.4/ 3(ここではC ++ 11標準を使用しています)が言うので、リターンタイプでも同じことを意味すると思うかもしれません。

クラスの注入されたクラス名(第9節)も、名前の非表示と検索の目的で、そのクラスのメンバーであると見なされます。

深く掘り下げる、§3.4.3.1/ 2、

コンストラクターが受け入れ可能なルックアップ結果であり、nested-name-specifierがクラスCを指定するルックアップでは、次のようになります。

—ネストされた名前指定子の後に指定された名前が、Cで検索されたときに、Cの注入されたクラス名である場合(第9節)

代わりに、名前はクラスCのコンストラクターに名前を付けると見なされます。

class {}注入されたクラス名で宣言を開始するコンテキストは、スコープ外のコンストラクターを定義する場合と同じです。

class Vector3 { … };

Vector3::Vector3(){m_x = m_y = m_z = 0.0f;}

古いGCCは、宣言がコンストラクターではないことに気づき、機能するフォールバックパスを取りました。ただし、C ++は、コンストラクターがルックアップの結果である可能性があるコンテキストでは、それが唯一の有効なルックアップ結果であると指定しているため、そのフォールバックは不正でした。

おそらく、一部のユーザーは時間をかけてバグを報告し、GCC開発者は時間をかけてこれを診断し、修正し、テストケースを作成しました。C ++のような複雑な言語での些細なことの数を掛け合わせると、コンパイラーに費やされた努力に感謝し始めます。

于 2013-01-24T02:52:13.920 に答える