Reputation: 2471
Three major compilers (gcc, clang, MSVC) happily compile the following example (godbolt):
struct Test
{
// Member type `Test::Test` is supposedly introduced at this point
// as an alias to `struct Test`, per
// https://timsong-cpp.github.io/cppwp/n4659/class#2
// Shouldn't the following declaration be rejected since it redefines
// the name `Test` in the same scope?
// https://timsong-cpp.github.io/cppwp/n4659/basic.lookup#3
int Test;
// Doing the same explicitly would be a compilation error, as expected:
// using Probe = int;
// int Probe;
};
int main()
{
Test x;
x.Test = 4;
}
Is the above example well-formed? and why. Why doesn't injected-class-name render the declaration of member int Test;
invalid?
Lookup rule [wrong reference to a newer standard] that might have made the example ill-formed with no diagnostic seem irrelevant, as no lookup happens here until the class is complete. What other clauses are relevant to this example?
Upvotes: 4
Views: 260
Reputation: 311126
According to the C++17 Standard (12.2 Class members)
18 If T is the name of a class, then each of the following shall have a name different from T:
(18.1) — every static data member of class T;
(18.2) — every member function of class T [ Note: This restriction does not apply to constructors, which do not have names (15.1) — end note ] ;
(18.3) — every member of class T that is itself a type;
(18.4) — every member template of class T;
(18.5) — every enumerator of every member of class T that is an unscoped enumerated type; and
(18.6) — every member of every anonymous union that is a member of class T.
and
19 In addition, if class T has a user-declared constructor (15.1), every non-static data member of class T shall have a name different from T.
So as your class does not have a user-declared constructor then its non-static data member Test
may have the same name as the class name.
You may even write
Test Test;
Test.Test = 4;
(It seems it is allowed for compatibility with C where structure tag names and names of data members belong to different name spaces.)
On the other hand, if you will declare a constructor as for example
struct Test
{
Test() = default;
int Test;
};
then the compiler will issue an error.
In general C++ does not allow for example to declare a variable and a function with the same name in the same scope.
Upvotes: 6