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?
source to share
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.
source to share
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
.
source to share