{"id":106367,"date":"2022-03-21T07:00:00","date_gmt":"2022-03-21T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106367"},"modified":"2024-10-05T18:22:01","modified_gmt":"2024-10-06T01:22:01","slug":"20220321-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220321-00\/?p=106367","title":{"rendered":"Injected class names: The C++ feature you didn&#8217;t even realize that you were using"},"content":{"rendered":"<p>C++ has a feature called <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/injected-class-name\"> injected class names<\/a>, which lets you refer to the class being defined by its plain name without needing to fully qualify it with namespaces and template parameters.<\/p>\n<p>You have probably been taking advantage of this feature without even realizing it:<\/p>\n<pre>template&lt;typename T&gt;\r\nstruct Wrapper\r\n{\r\n    Wrapper() { \/* constructor *\/ }\r\n};\r\n<\/pre>\n<p>That <code>Wrapper()<\/code> is using the injected class name. The full name of the constructor is<\/p>\n<pre>    Wrapper&lt;T&gt;() { \/* constructor *\/ }\r\n<\/pre>\n<p>but C++ secretly injects the simple name of the class into the class itself, as if you had written<\/p>\n<pre>    using Wrapper = Wrapper&lt;T&gt;;\r\n<\/pre>\n<p>Injected class names are public and therefore can be inherited:<\/p>\n<pre>namespace details {\r\n    struct Base\r\n    {\r\n        Base(int) { \/* constructor *\/ }\r\n    };\r\n}\r\n\r\nstruct Derived : details::Base\r\n{\r\n    Derived() : Base(42) { \/* constructor *\/ }\r\n}\r\n<\/pre>\n<p>The construction of the base class from the derived class can be done by writing just <code>Base(42)<\/code> instead of the full name <code>details::Base(42)<\/code>. The injection goes like this:<\/p>\n<pre>namespace details {\r\n    struct Base\r\n    {\r\n        <span style=\"border: solid 1px currentcolor;\">using Base = ::details::Base; \/\/ injected<\/span>\r\n        Base(int) { \/* constructor *\/ }\r\n    };\r\n}\r\n\r\nstruct Derived : details::Base\r\n{\r\n    Derived() : Base(42) { \/* constructor *\/ }\r\n};\r\n<\/pre>\n<p>When you write <code>Base<\/code> inside the definition of <code>Derived<\/code>, you are using the name <code>Base<\/code> that was defined way over there in the <code>Base<\/code> class.<\/p>\n<p>Note that making base classes private prevents their types from being inherited:<\/p>\n<pre>namespace details {\r\n    struct Base { };\r\n    struct Middle : <span style=\"border: solid 1px currentcolor;\">private<\/span> Base { };\r\n}\r\n\r\nstruct Derived : details::Middle\r\n{\r\n    void blah()\r\n    {\r\n        Middle m; \/\/ \"Middle\" accessible from details::Middle\r\n        Base b; \/\/ \"Base\" not accessible because it was privately inherited\r\n        details::Base b; \/\/ Need to use the full name\r\n    }\r\n};\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Simplifying the name of what you are.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-106367","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Simplifying the name of what you are.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=106367"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106367\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=106367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}