{"id":109108,"date":"2023-12-06T07:00:00","date_gmt":"2023-12-06T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109108"},"modified":"2023-12-06T09:19:49","modified_gmt":"2023-12-06T17:19:49","slug":"20231206-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20231206-00\/?p=109108","title":{"rendered":"In C++, how can I make a member function default parameter depend on <CODE>this<\/CODE>?"},"content":{"rendered":"<p>In C++, you can define a default parameter, but among the constraints on the default parameter is that it may not be <code>this<\/code> or anything that depends on <code>this<\/code> like a member variable or call to another member function.<\/p>\n<pre>struct Sample\r\n{\r\n    int increment;\r\n    void add(int v = <span style=\"border: solid 1px currentcolor;\">increment<\/span>); \/\/ not allowed\r\n    void notify_all(Sample* source = <span style=\"border: solid 1px currentcolor;\">this<\/span>); \/\/ not allowed\r\n};\r\n<\/pre>\n<p>Although it is not allowed, you can fake it:<\/p>\n<pre>struct Sample\r\n{\r\n    int increment;\r\n\r\n    void add(int v);\r\n    <span style=\"border: solid 1px currentcolor;\">void add() { add(increment); }<\/span>\r\n\r\n    void notify_all(Sample* source);\r\n    <span style=\"border: solid 1px currentcolor;\">void notify_all() { notify_all(this); }<\/span>\r\n};\r\n\r\nSample s;\r\n\r\ns.add(2); \/\/ adds 2\r\ns.add(); \/\/ adds s.increment\r\n\r\ns.notify_all(); \/\/ uses source = s\r\ns.notify_all(other); \/\/ uses source = other\r\n<\/pre>\n<p>This is an overload, rather than a default parameter. Whereas default parameters allow you to call the same function in multiple ways, overloads are separate functions entirely. This means that creating a pointer to a member function is much more frustrating for overloads since you have to specify which overload you are trying to use.<\/p>\n<pre>void (S::*f)() = &amp;S::add; \/\/ selects S::add()\r\nvoid (S::*f)(int) = &amp;S::add; \/\/ selects S::add(int)\r\nauto f = &amp;S::add; \/\/ error: ambiguous\r\nauto f = static_cast&lt;void(S::*)()&gt;(&amp;S::add); \/\/ selects S::add()\r\n<\/pre>\n<p>This complexity with producing pointers to overloaded member functions <a title=\"I get a weird error about no matching function when I try to use winrt::capture\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200918-45\/?p=104239\"> bit us earlier when we tried to use <code>winrt::capture<\/code><\/a>. We can work around this by providing non-overloaded alternatives for cases where you would prefer that each overload have a unique name.<\/p>\n<pre>struct Sample\r\n{\r\n    int increment;\r\n\r\n    void add(int v);\r\n    void add() { add(increment); }\r\n    <span style=\"border: solid 1px currentcolor; border-bottom: none;\">void add0() { add(); }      <\/span>\r\n    <span style=\"border: solid 1px currentcolor; border-top: none;\">void add1(int v) { add(v); }<\/span>\r\n\r\n    void notify_all(Sample* source);\r\n    void notify_all() { notify_all(this); }\r\n    <span style=\"border: solid 1px currentcolor; border-bottom: none;\">void notify_all0() { notify_all(); }                    <\/span>\r\n    <span style=\"border: solid 1px currentcolor; border-top: none;\">void notify_all1(Sample* source) { notify_all(source); }<\/span>\r\n};\r\n\r\ns.add();  \/\/ this calls the 0-parameter version\r\ns.add(2); \/\/ this calls the 1-parameter version\r\n\r\nauto f = &amp;S::add; \/\/ error: ambiguous\r\nauto f = &amp;S::add0; \/\/ This is the zero-parameter version\r\nauto f = &amp;S::add1; \/\/ This is the one-parameter version\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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-109108","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can&#8217;t, but you can fake it.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109108","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=109108"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109108\/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=109108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}