{"id":109115,"date":"2023-12-07T07:00:00","date_gmt":"2023-12-07T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109115"},"modified":"2023-12-07T10:49:17","modified_gmt":"2023-12-07T18:49:17","slug":"20231207-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20231207-00\/?p=109115","title":{"rendered":"In C++, how can I make a default parameter be the <CODE>this<\/CODE> pointer of the caller?"},"content":{"rendered":"<p>Consider the following class:<\/p>\n<pre>struct Property\r\n{\r\n    Property(char const* name, int initial, Object* owner) :\r\n        m_name(name), m_value(initial), m_owner(owner) {}\r\n\r\n    \u27e6 other methods elided - use your imagination \u27e7\r\n\r\n    char const* m_name;\r\n    Object* m_owner;\r\n    int m_value;\r\n};\r\n<\/pre>\n<p>Suppose the idea is that you have a class that has a bunch of properties as members, and the containing class serves as the owner.<\/p>\n<pre>struct Widget : Object\r\n{\r\n    Property Height{ \"Height\", 10, this };\r\n    Property Width{ \"Width\", 10, this };\r\n};\r\n<\/pre>\n<p>Now, it&#8217;s a bit annoying having to say <code>this<\/code> each time you define a property. Is there some way that the <code>Property<\/code> constructor can infer the class that is creating it?<\/p>\n<p><a title=\"In\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20231206-00\/?p=109108\"> You can&#8217;t make a member function default parameter dependent upon its own <code>this<\/code><\/a>, but what about making it dependent on the caller&#8217;s <code>this<\/code>?<\/p>\n<p>No, that doesn&#8217;t work either. Default parameters are resolved at the point of declaration, not at the point of invocation.<\/p>\n<pre>int v;\r\n\r\nnamespace N\r\n{\r\n    int v;\r\n\r\n    struct Example\r\n    {\r\n        Example(int value = v);\r\n    };\r\n\r\n}\r\n\r\nvoid test()\r\n{\r\n    int v;\r\n    N::Example e; \/\/ which \"v\" does this use?\r\n}\r\n<\/pre>\n<p>The answer is that it uses <code>N::v<\/code>, because that is the <code>v<\/code> that is found at the point the <code>int value = v<\/code> is encountered. The local variable <code>v<\/code> is not considered because it is not in scope, and the global variable <code>::v<\/code> is not considered because it has been shadowed by <code>N::v<\/code>. It is irrelevant that <code>::v<\/code> and the local variable <code>v<\/code> are in scope and visible at the time the constructor is called.\u00b9<\/p>\n<p>But again, all is not lost. We just have to find another trick.<\/p>\n<pre>struct Widget : Object\r\n{\r\n    Property Prop(char const* name, int initial)\r\n    { return Property(name, initial, this); }\r\n\r\n    Property Height{ Prop(\"Height\", 10) };\r\n    Property Width{ Prop(\"Width\", 10) };\r\n};\r\n<\/pre>\n<p>The trick is to declare a helper method inside <code>Widget<\/code> that creates the <code>Property<\/code> and adds the <code>Widget<\/code>&#8216;s <code>this<\/code> pointer as the final parameter.<\/p>\n<p>You can make this reusable by factoring it into a helper base class that uses the curiously recurring template pattern (commonly known as CRTP).<\/p>\n<pre>template&lt;typename D&gt;\r\nstruct PropertyHelper\r\n{\r\n    Property Prop(char const* name, int initial)\r\n    { return Property(name, initial, static_cast&lt;D*&gt;(this)); }\r\n};\r\n\r\nstruct Widget : Object, <span style=\"border: solid 1px currentcolor;\">PropertyHelper&lt;Widget&gt;<\/span>\r\n{\r\n    Property Height{ Prop(\"Height\", 10) };\r\n    Property Width{ Prop(\"Width\", 10) };\r\n};\r\n<\/pre>\n<p>If you have access to <a title=\"C++23's Deducing this: what it is, why it is, how to use it\" href=\"https:\/\/devblogs.microsoft.com\/cppblog\/cpp23-deducing-this\/\"> C++23&#8217;s deducing this<\/a>, then you can simplify it further:<\/p>\n<pre>struct PropertyHelper\r\n{\r\n    template&lt;typename Parent&gt;\r\n    Property Prop(this Parent&amp;&amp; parent, char const* name, int initial)\r\n    { return Property(name, initial, &amp;parent); }\r\n};\r\n\r\nstruct Widget : Object, <span style=\"border: solid 1px currentcolor;\">PropertyHelper<\/span>\r\n{\r\n    Property Height{ Prop(\"Height\", 10) };\r\n    Property Width{ Prop(\"Width\", 10) };\r\n};\r\n<\/pre>\n<p>You can go even further and just put <code>Prop()<\/code> in the <code>Object<\/code>.<\/p>\n<pre>struct Object\r\n{\r\n    \u27e6 other methods elided - use your imagination \u27e7\r\n\r\n    template&lt;typename Parent&gt;\r\n    Property Prop(this Parent&amp;&amp; parent, char const* name, int initial)\r\n    { return Property(name, initial, &amp;parent); }\r\n\r\n};\r\n\r\nstruct Widget : Object\r\n{\r\n    Property Height{ Prop(\"Height\", 10) };\r\n    Property Width{ Prop(\"Width\", 10) };\r\n};\r\n<\/pre>\n<p>Is this an improvement over typing <code>this<\/code> repeatedly? I&#8217;m not sure.<\/p>\n<p>\u00b9 If we had moved the declaration of <code>N::v<\/code> to after the definition of <code>struct Example<\/code>, then the <code>int value = v<\/code> would have resolved to <code>::v<\/code>, since <code>N::v<\/code> hasn&#8217;t been declared yet.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Again, you can&#8217;t, but you can fake it.<\/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-109115","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Again, you can&#8217;t, but you can fake it.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109115","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=109115"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109115\/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=109115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}