Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

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.

share|improve this question
    
Why was the language-lawyer tag removed? – giusti 6 hours ago
    
@giusti I have just reinserted the tag – João Afonso 6 hours ago
3  
There's some gray area of course. The general trend I've seen in C++ language-lawyer questions has been towards compiler's disagreeing, or programs compiling without assurance of them being well-defined behavior. These would be places for the "language lawyers" to debate what which compiler was behaving correctly, or whether a program meets the standards requirements for being well defined. Since you should be receiving an accurate error message from this code, IMO it falls outside what is generally posted with [language-lawyer] – Ryan Haining 5 hours ago
2  
Actually, this doesn't seem a good candidate for the language-lawyer tag. The standard is clear and the snippet is ill-formed. That's all. My two cents. – skypjack 5 hours ago
1  
@RyanHaining AFAIK language-lawyer simply states that the OP wants a precise reference from the official standard that clarifies what happens in the question. Hence, question about any behaviour can be asked with said tag, whether you find them interesting or not. – Bakuriu 4 hours ago
up vote 11 down vote accepted

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.

share|improve this answer
    
1) [basic.scope.pdecl]/7 starts with the following statement: The point of declaration of a class **first** declared in an elaborated-type-specifier is as follows:. That means, that bullet points (7.1) and (7.2) are considered only if the declaration class A; is first declared in an elaborated-type-specifier, which is not the case in both examples, as I pointed out at the end of my question. – João Afonso 3 hours ago
    
2) So, as far as [basic.scope.pdecl]/7 is concerned, I don't think we can say that the declaration struct A; in main(), in my second example, cannot refer to a class declared in outer scope, as you asserted above. Thanks for your reply anyway. – João Afonso 3 hours ago
    
I explained why, in your second example, struct A; is the first declaration of A, because the A at global scope is a completely different class with the same name. – Oktalist 2 hours ago
    
[basic.scope.declarative]/1: "The scope of a declaration is the same as its potential scope unless the potential scope contains another declaration of the same name. In that case, the potential scope of the declaration in the inner declarative region is excluded from the scope of the declaration in the outer declarative region." – Oktalist 2 hours ago
1  
I think I found the answer to my question in [class.name]/2 which states exactly what you said in your answer (Under no circumstances can it refer to a class declared in an outer scope.). Thanks (+1). – João Afonso 1 hour ago

In the second example the line struct A; is a forward declaration for a struct called A in the main function's scope. This struct will be preferred to the global struct A. The next line defines a variable called a of type struct A. Since a struct A was declared in the main function's scope, that's where the compiler will search for it's definition there. It fails to find one (it's commented out). The first example compiles because there is definition in the same scope. The following example will compile however because it specified that A is in the global namespace :

struct A{ int i = 10; };

int main() {
//    struct A{ int i = 20; };
    struct A;
    struct ::A a;
}
share|improve this answer
2  
I would mention explicitly the fact that's a forward declaration. – skypjack 5 hours ago
    
@skypjack Thank you. I will fix the oversight. – François Andrieux 5 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.