164

Recently, I saw a strange C++ feature: injected class name.

class X { };
X x1;
class X::X x2; // class X::X is equal to X
class X::X::X x3; // ...and so on...

But I cannot figure out why this feature is necessary. Is there any practice that requires this feature?

And I heard this feature didn't exist in old C++. Then, when was it introduced? C++03? C++11?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
ikh
  • 10,119
  • 1
  • 31
  • 70

1 Answers1

181

The injected class name means that X is declared as a member of X, so that name lookup inside X always finds the current class, not another X that might be declared at the same enclosing scope, e.g.

void X() { }
class X {
public:
  static X create() { return X(); }
};

Is the create() function creating a temporary X object or calling the function X? At namespace scope it would call the function, so the purpose of the injected-class-name is to ensure that within the body of X the name always finds the class itself (because name lookup starts in the class' own scope before looking in the enclosing scope).

It's also helpful inside class templates, where the injected class name can be used without a template argument list, e.g. using simply Foo instead of the full template-id Foo<blah, blah, blah>, so it's easy to refer to the current instantiation. See DR 176 for a change between C++98 and C++03 that clarified that.

The idea of the injected class name was present in C++98, but the terminology was new for C++03.

C++98 says:

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself.

The second sentence was changed by DR 147 so C++03 says in [class]/2:

A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.

Even before C++98, the ARM has roughly equivalent wording that means the class' name can always be used in the class body to refer to the class itself:

The name of a class can be used as a class-name even within the member-list of the class specifier itself.

  • For example,

    class link { link* next; };

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 4
    I got asked that pretty often, but never could build up a simple example pointing the problem. So +1 For the example. – dhein Aug 29 '14 at 09:26
  • 1
    This can be seen clearly if you run clang++ your_program.cpp -Xclang -ast-dump and you see your class and then an injected class child node. – xaxxon Jun 24 '16 at 11:19
  • note that `X()` is `void` so you can't actually `return X()` even if it can looks up that function – phuclv Jun 03 '22 at 02:55
  • @phuclv yes, but that's not really the point here. If it bothers you, change the global function to `int X();` and then add a constructor `X(int)` to the class, so that if lookup did find the function, it might be usable. The main point still holds: the injected-class-name ensures the class itself is found, not something else with that name. – Jonathan Wakely Jun 08 '22 at 10:52