以下のスニペットはコンパイルします( demo ):
_struct A{ int i = 10; };
int main() {
struct A{ int i = 20; };
struct A;
struct A a;
}
_
しかし、これはそうではありません:
_struct A{ int i = 10; };
int main() {
// struct A{ int i = 20; };
struct A;
struct A a;
}
_
答えはおそらく標準のこれらの段落によって与えられていることがわかります:
[basic.lookup.elab]/2 および [basic.scope.pdecl]/7 。
しかし、これらの2つの段落から上記のさまざまな動作を推測する方法は本当にわかりません。
最初の例では、_struct A
_は not で最初にelaborated-type-specifier_struct A;
_、ただしmain()
の_struct A
_の定義。
2番目の例では、_struct A
_も not で最初にelaborated-type-specifier_struct A;
_、ただしグローバルスコープの_struct A
_の定義。
それぞれの例には、A
という名前の2つの異なるクラスの宣言が含まれています。
クラスの1つをB
に名前変更して、クラスを区別しましょう。
struct A{ int i = 10; };
int main() {
struct B{ int i = 20; };
struct B;
struct B b;
}
上記は、最初の例と意味的に同じです。クラスA
は使用されません。
struct A{ int i = 10; };
int main() {
struct B;
struct B b;
}
これは、2番目の例と意味的に同じです。不完全な型のオブジェクト、前方宣言されたクラスB
を作成しようとしています。
B
の名前を変更してA
に戻すことは、A
のmain
の宣言が他のA
の宣言を隠すため、何も変更しません。グローバルな範囲で。
[basic.lookup.elab]/2
elaborated-type-specifierがnested-name-specifierを持たない場合、およびelaborated-type-specifierは、次の形式の宣言に表示されます。
class-key
attribute-specifier-seq
optidentifier
;
elaborated-type-specifierは、[basic.scope.pdecl]で説明されているように、class-nameを導入する宣言です。
そう struct A;
は宣言であり、その紹介は宣言のスコープ内のクラス名です。いかなる状況でも、外部スコープで宣言されたクラスを参照することはできません。
[basic.scope.pdecl]/7
[注:他の形式のelaborated-type-specifierは、新しい名前を宣言しません[...] —end note]
暗黙的に、この形式のelaborated-type-specifierは新しい名前を宣言します。
2番目の例では、行struct A;
は、メイン関数のスコープ内のAという構造体の前方宣言です。この構造体は、グローバルstruct A
よりも優先されます。次の行は、struct A
型のa
という変数を定義します。 struct A
がメイン関数のスコープで宣言されたため、コンパイラはそこでその定義を検索します。 1つが見つかりません(コメント化されています)。同じスコープ内に定義があるため、最初の例はコンパイルされます。ただし、次の例は、A
がグローバル名前空間にあることを指定しているため、コンパイルされます。
struct A{ int i = 10; };
int main() {
// struct A{ int i = 20; };
struct A;
struct ::A a;
}
Aの定義が見つからないため、コンパイルされません。
int main() {
// struct A{ int i = 20; };
struct A;
struct A a;
}
上記のコードは、グローバルAがローカルAによってシャドウされるため、最初の例と同じです。2番目の例では、Aには定義がありません。これは単なるプロトタイプです。プロトタイプは、定義が必要なコードの後に定義が配置されるときに、定義が必要なコードの前に配置されることになっています。コンパイラがその定義を見つけることができない場合、Aが何であるかがわからないため失敗します(グローバル定義はローカルプロトタイプによってシャドウされ、無視されます)。