Is my interpretation of the word "first" correct in 3.3.2 / 6?
In the snippet below I can understand (from point 3.3.2 / 6 seconds) that the name B
in the declaration struct B* p;
is injected into the global namespace as the class name.
struct A {
// struct B{};
int B;
struct B* p;
};
void f(B&) {}
int main()
{
A a;
f(*a.p);
}
ยง3.3.2 / 6:
The point of class declaration is the first one declared in the specified type-specifier looks like this:
to declare a form
class-key attribute-seq-specifier opt identifier;
the identifier is declared as the name of the class in the scope that contains the declaration, otherwise
for the specified form-specifier type
class id
if a specated-type is used in a decl-specifier-seq or a declaration parameter of a function defined in a namespace scope, the identifier is declared as a class name in the namespace that contains the declaration; otherwise, other than declaring a friend, the identifier is declared in the smallest namespace or block that the declaration contains. [Note. These rules also apply in templates. - end note] [Note. Other forms of the specified type specifier do not declare a new name and therefore refer to an existing type name. See 3.4.4 and 7.1.6.3. - end of note]
However, if I uncomment the definition struct B{};
inside struct A
, what I said earlier regarding the injection of a name B
into the global namespace no longer occurs since the code does not compile.I suppose it is related to the word first (emphasis mine) above, since now the class name B
in the declaration is struct B* p;
no longer its first declaration in its declarative region . Did I say it correctly?
Assuming my interpretation is correct, why is the class name B
not being entered into the global namespace in this case ? Note that the nested class struct B{};
will be hidden inside A in this case, that is, even if we change the function declaration f
to void f(A::B&)
, the code will not compile.
There is one more point that I don't understand: what did the developers decide to inject the class into the namespace, or block the scope containing the specified type-specifier at the second bullet point above? That is, why didn't they leave the class name declaration inside the class scope?
You are correct that the first keyword in ยง3.3.2 / 6 is also the reason for the following:
struct A {
struct B *p;
struct B{};
int b;
};
void f(B* arg) {
std::cout << std::is_same<decltype(arg), A::B*>::value; // not the same type
}
int main()
{
A a;
f(a.p);
}
why in this case the class name B is not injected into the global namespace?
As dyp pointed out, [basic.lookup.elab] / 2 explains that 3.3.2 is only executed if no previous declaration could be found
If a specified type-specifier is entered by a class key and this lookup does not find a previously declared type name, or if the specified type-specifier appears in a declaration with the form:
class-specifier-attribute identifier;
The developed type-specifier is a declaration that introduces the class-name as described in section 3.3.2.the
Finally, I tracked down this behavior, possibly inheriting from C99 6.7.2.3/p8
If the form type specifier is
struct-or-union identifier
occurs other than as part of one of the above forms, and no other declaration of an identifier as a tag, then it declares an incomplete structure or union, and declares an identifier as a tag of this type .113)
113) There is no such enumeration construct.
I would say your interpretation is correct. When you uncomment struct B{};
, the line struct B* p;
will simply refer to this struct A::B
.
To answer your question why, when you leave struct B {};
commented out, the name is struct B
inserted into the global scope. I would say that since the authors didn't want you to (somewhat) silently declare B
as a member A
without using a member spec for the name B
.