Can a member of a class be named the same name as

2019-01-27 18:31发布

问题:

Trying to compile the following code on different compilers gives me two different results:

struct S{};
struct T{S S;};
int main(){}

As you can see, inside T, I have an object named the same as the previously defined class S.


On GCC 4.7.2, I get the following error pertaining to the S S; declaration inside T:

error: declaration of 'S T::S' [-fpermissive]
error: changes meaning of 'S' from 'struct S' [-fpermissive]

However, moving it outside of the class (or into main) works fine:

struct S{};
S S;
int main(){}

What exactly does it mean by the error it's giving me?


In Visual Studio 2012, the whole thing compiles and runs without any errors. Pasting it into this Clang 3.0 compiler gives me no errors as well.

Which is right? Can I actually do this or not?

回答1:

gcc is correct, from [3.3.7 Class Scope]

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

However, note that no diagnostic is required, so all compilers are conforming.

The reason is because of how class scope works. When you write S S; S is visible within the entire class and changes the meaning when you use S.

struct S{};
struct T{
    void foo()
    { 
        S myS; // Not possible anymore because S refers to local S
    }
    S S;
};


回答2:

This code is ill-formed, no diagnostic required. Like the diagnostic says, if a declaration uses a name and the name has a different meaning than it would have when looked up at the end of the class definition, the programm is illformed, no diagnostic required.



回答3:

@JesseGood provide a complete answer, but if you really want to do this without any error, you can use type's full name and it will work as follow:

struct S {};
struct T { ::S S; };
int main() {return 0;}

No there is no error, since S in your class is T::S and its type is ::S!