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 Ain 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
Ais 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
Bback toAdoesn't change anything because then the declaration ofAinmainshadows the declaration of the otherAat 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.