12

異なるコンパイラで次のコードをコンパイルしようとすると、2つの異なる結果が得られます。

struct S{};
struct T{S S;};
int main(){}

ご覧のとおり、内部Tには、以前に定義したクラスと同じ名前のオブジェクトがありますS


GCC 4.7.2では、内部の宣言に関連して次のエラーが発生します。S S;T

エラー:「ST :: S」の宣言[-fpermissive]
エラー:「S」の意味を「structS」から変更します[-fpermissive]

ただし、クラス外(またはクラス内main)に移動すると正常に機能します

struct S{};
S S;
int main(){}

それが私に与えるエラーとは正確にはどういう意味ですか?


Visual Studio 2012では、すべてがエラーなしでコンパイルおよび実行されます。このClang3.0コンパイラに貼り付けると、エラーも発生しません。

どちらが正しいですか?私は実際にこれを行うことができますか?

4

3 に答える 3

16

[3.3.7クラススコープ]からのgccは正しいです

クラスSで使用される名前Nは、そのコンテキストで、Sの完全なスコープで再評価されるときに、同じ宣言を参照するものとします。このルールの違反に対して診断は必要ありません。

ただし、no diagnostic is requiredすべてのコンパイラが準拠していることに注意してください。

その理由は、クラススコープがどのように機能するかによるものです。書くとクラス全体S S; Sに表示され、使用すると意味が変わります。S

struct S{};
struct T{
    void foo()
    { 
        S myS; // Not possible anymore because S refers to local S
    }
    S S;
};
于 2012-10-17T21:34:58.690 に答える
8

@JesseGoodは完全な答えを提供しますが、本当にエラーなしでこれを実行したい場合は、タイプのフルネームを使用でき、次のように機能します。

struct S {};
struct T { ::S S; };
int main() {return 0;}

SあなたのクラスにはがT::Sあり、そのタイプは::S!なので、エラーはありません。

于 2012-10-17T22:38:19.333 に答える
6

このコードは形式が正しくなく、診断は必要ありません。診断が言うように、宣言が名前を使用し、その名前がクラス定義の最後で調べたときとは異なる意味を持っている場合、プログラムは不正であり、診断は必要ありません。

于 2012-10-17T21:34:44.167 に答える