March 21st, 2022

Injected class names: The C++ feature you didn’t even realize that you were using

C++ has a feature called injected class names, which lets you refer to the class being defined by its plain name without needing to fully qualify it with namespaces and template parameters.

You have probably been taking advantage of this feature without even realizing it:

template<typename T>
struct Wrapper
{
    Wrapper() { /* constructor */ }
};

That Wrapper() is using the injected class name. The full name of the constructor is

    Wrapper<T>() { /* constructor */ }

but C++ secretly injects the simple name of the class into the class itself, as if you had written

    using Wrapper = Wrapper<T>;

Injected class names are public and therefore can be inherited:

namespace details {
    struct Base
    {
        Base(int) { /* constructor */ }
    };
}

struct Derived : details::Base
{
    Derived() : Base(42) { /* constructor */ }
}

The construction of the base class from the derived class can be done by writing just Base(42) instead of the full name details::Base(42). The injection goes like this:

namespace details {
    struct Base
    {
        using Base = ::details::Base; // injected
        Base(int) { /* constructor */ }
    };
}

struct Derived : details::Base
{
    Derived() : Base(42) { /* constructor */ }
};

When you write Base inside the definition of Derived, you are using the name Base that was defined way over there in the Base class.

Note that making base classes private prevents their types from being inherited:

namespace details {
    struct Base { };
    struct Middle : private Base { };
}

struct Derived : details::Middle
{
    void blah()
    {
        Middle m; // "Middle" accessible from details::Middle
        Base b; // "Base" not accessible because it was privately inherited
        details::Base b; // Need to use the full name
    }
};
Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • 紅樓鍮 · Edited

    Injected class names are public and therefore can be inherited

    Unfortunately those names aren't useful if your base classes are dependent (on template parameters), since you have to qualify them with the specific base class they're from if you want to refer to them, which in this case defeats the purpose of injected class names completely. This frustration is especially frequently encountered when one uses CRTP.

    Bonus chatter: I'd actually like the injected class names to...

    Read more