The snippet below compiles (demo):
struct A{ int i = 10; };
int main() {
struct A{ int i = 20; };
struct A;
struct A a;
}
But this doesn't:
struct A{ int i = 10; };
int main() {
// struct A{ int i = 20; };
struct A;
struct A a;
}
I can see that the answer is probably given by these paragraphs in the Standard:
[basic.lookup.elab]/2 and [basic.scope.pdecl]/7.
But I really don't know how to deduce the different behaviors shown above from these two paragraphs.
Note that in the first example the struct A
is not first declared in the elaborated-type-specifier struct A;
, but in the definition of struct A
in main()
.
In the second example, the struct A
is also not first declared in the elaborated-type-specifier struct A;
, but in the definition of struct A
in global scope.
Each of the examples contains declarations of two different classes, both with the name
A
.Let's distinguish between the classes by renaming one of them to
B
:The above is semantically identical to your first example. The class
A
is never used.This is semantically identical to your second example. You are trying to create an object of an incomplete type, the forward-declared class
B
.Renaming
B
back toA
doesn't change anything because then the declaration ofA
inmain
shadows the declaration of the otherA
at global scope.[basic.lookup.elab]/2
So
struct A;
is a declaration that introduces the class name in the scope of the declaration. Under no circumstances can it refer to a class declared in an outer scope.[basic.scope.pdecl]/7
By implication, this form of elaborated-type-specifier declares a new name.