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;


ยง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 - 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

2 answers

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;


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

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




All Articles