Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The first snippet below compiles, but the second doesn't. Why?

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.

like image 683
João Afonso Avatar asked Jan 04 '17 19:01

João Afonso


1 Answers

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:

struct A{ int i = 10; };  int main() {     struct B{ int i = 20; };     struct B;     struct B b; } 

The above is semantically identical to your first example. The class A is never used.

struct A{ int i = 10; };  int main() {     struct B;     struct B b; } 

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 to A doesn't change anything because then the declaration of A in main shadows the declaration of the other A at global scope.

[basic.lookup.elab]/2

If the elaborated-type-specifier has no nested-name-specifier, and [...] if the elaborated-type-specifier appears in a declaration with the form:

class-key attribute-specifier-seqopt identifier ;

the elaborated-type-specifier is a declaration that introduces the class-name as described in [basic.scope.pdecl].

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

[ Note: Other forms of elaborated-type-specifier do not declare a new name [...] — end note ]

By implication, this form of elaborated-type-specifier declares a new name.

like image 117
Oktalist Avatar answered Sep 20 '22 23:09

Oktalist