{"id":30707,"date":"2022-06-27T10:41:41","date_gmt":"2022-06-27T10:41:41","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=30707"},"modified":"2022-06-27T16:58:17","modified_gmt":"2022-06-27T16:58:17","slug":"cpp23-deducing-this","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/cpp23-deducing-this\/","title":{"rendered":"C++23&#8217;s Deducing this: what it is, why it is, how to use it"},"content":{"rendered":"<p><a href=\"https:\/\/wg21.link\/p0847\">Deducing <code>this<\/code><\/a> (P0847) is a C++23 feature which gives a new way of specifying non-static member functions. Usually when we call an object&#8217;s member function, the object is <em>implicitly<\/em> passed to the member function, despite not being present in the parameter list. P0847 allows us to make this parameter <em>explicit<\/em>, giving it a name and <code>const<\/code>\/reference qualifiers. For example:<\/p>\n<pre><code class=\"language-cpp\">struct implicit_style {\r\n    void do_something(); \/\/object is implicit\r\n};\r\n\r\nstruct explicit_style {\r\n    void do_something(this explicit_style&amp; self); \/\/object is explicit\r\n};<\/code><\/pre>\n<p>The explicit object parameter is distinguished by the keyword <code>this<\/code> placed before the type specifier, and is only valid for the first parameter of the function.<\/p>\n<p>The reasons for allowing this may not seem immediately obvious, but a bunch of additional features fall out of this almost by magic. These include de-quadruplication of code, recursive lambdas, passing <code>this<\/code> by value, and a version of the <a href=\"https:\/\/www.fluentcpp.com\/2017\/05\/12\/curiously-recurring-template-pattern\/\">CRTP<\/a> which doesn&#8217;t require the base class to be templated on the derived class.<\/p>\n<p>This post will walk through an overview of the design, then many of the cases you can use this feature for in your own code.<\/p>\n<p>For the rest of this blog post I&#8217;ll refer to the feature as &#8220;explicit object parameters&#8221;, as it makes more sense as a feature name than &#8220;deducing <code>this<\/code>&#8220;. Explicit object parameters are supported in MSVC as of Visual Studio 2022 version 17.2. A good companion to this post is Ben Deane&#8217;s talk <a href=\"https:\/\/www.youtube.com\/watch?v=jXf--bazhJw\">Deducing <code>this<\/code> Patterns<\/a> from CppCon.<\/p>\n<h2>Overview<\/h2>\n<p>The paper which proposed this feature was written by <a href=\"https:\/\/twitter.com\/atomgalaxy\">Ga\u0161per A\u017eman<\/a>, <a href=\"https:\/\/twitter.com\/ben_deane\">Ben Deane<\/a>, <a href=\"https:\/\/twitter.com\/BarryRevzin\">Barry Revzin<\/a>, and <a href=\"https:\/\/twitter.com\/TartanLlama\">myself<\/a>, and was guided by the experience of <a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2021\/p0847r7.html#acknowledgements\">many experts in the field<\/a>. Barry and I began writing a version of this paper after we each implemented <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/optional\"><code>std::optional<\/code><\/a> and came across the same problem. We would be writing the <code>value<\/code> function of <code>optional<\/code> and, like good library developers, we&#8217;d try to make it usable and performant in as many use-cases as we could. So we&#8217;d want <code>value<\/code> to return a <code>const<\/code> reference if the object it was called on was <code>const<\/code>, we&#8217;d want it to return an rvalue if the object it was called on was an rvalue, etc. It ended up looking like this:<\/p>\n<pre><code class=\"language-cpp\">template &lt;typename T&gt;\r\nclass optional {\r\n  \/\/ version of value for non-const lvalues\r\n  constexpr T&amp; value() &amp; {\r\n    if (has_value()) {\r\n      return this-&gt;m_value;\r\n    }\r\n    throw bad_optional_access();\r\n  }\r\n\r\n  \/\/ version of value for const lvalues\r\n  constexpr T const&amp; value() const&amp; {\r\n    if (has_value()) {\r\n      return this-&gt;m_value;\r\n    }\r\n    throw bad_optional_access();\r\n  }\r\n\r\n  \/\/ version of value for non-const rvalues... are you bored yet?\r\n  constexpr T&amp;&amp; value() &amp;&amp; {\r\n    if (has_value()) {\r\n      return std::move(this-&gt;m_value);\r\n    }\r\n    throw bad_optional_access();\r\n  }\r\n\r\n  \/\/ you sure are by this point\r\n  constexpr T const&amp;&amp; value() const&amp;&amp; {\r\n    if (has_value()) {\r\n      return std::move(this-&gt;m_value);\r\n    }\r\n    throw bad_optional_access();\r\n  }\r\n  \/\/ ...\r\n};<\/code><\/pre>\n<p>(If you&#8217;re not familiar with the <code>member_function_name() &amp;<\/code> syntax, this is called &#8220;ref-qualifiers&#8221; and you can find more info <a href=\"https:\/\/akrzemi1.wordpress.com\/2014\/06\/02\/ref-qualifiers\/\">on Andrzej Krzemie\u0144ski&#8217;s blog<\/a>. If you&#8217;re not familiar with rvalue references (<code>T&amp;&amp;<\/code>) you can read up on move semantics <a href=\"https:\/\/stackoverflow.com\/questions\/3106110\/what-is-move-semantics\">on this Stack Overflow question<\/a>)<\/p>\n<p>Note the near-identical implementations of four versions of the same function, only differentiated on whether they&#8217;re <code>const<\/code> and whether they move the stored value instead of copying it.<\/p>\n<p>Barry and I would then move on to some other function and have to do the same thing. And again and again, over and over, duplicating code, making mistakes, building maintenance headaches for the future versions of ourselves. &#8220;What if&#8221;, we thought, &#8220;you could just write this?&#8221;<\/p>\n<pre><code class=\"language-cpp\">template &lt;typename T&gt;\r\nstruct optional {\r\n  \/\/ One version of value which works for everything\r\n  template &lt;class Self&gt;\r\n  constexpr auto&amp;&amp; value(this Self&amp;&amp; self) {\r\n    if (self.has_value()) {\r\n        return std::forward&lt;Self&gt;(self).m_value;\r\n    }\r\n    throw bad_optional_access();\r\n  }<\/code><\/pre>\n<p>(If you&#8217;re not familiar with <code>std::forward<\/code>, you can read about perfect forwarding <a href=\"https:\/\/eli.thegreenplace.net\/2014\/perfect-forwarding-and-universal-references-in-c\">on Eli Bendersky&#8217;s blog<\/a>)<\/p>\n<p>This does the same thing as the above four overloads, but in a single function. Instead of writing different versions of <code>value<\/code> for <code>const optional&amp;<\/code>, <code>const optional&amp;&amp;<\/code>, <code>optional&amp;<\/code>, and <code>optional&amp;&amp;<\/code>, we write one function template which <em>deduces<\/em> the <code>const<\/code>\/<code>volatile<\/code>\/reference (cvref for short) qualifiers of the object the it is called on. Making this change for almost every function in the type would cut down our code by a huge amount.<\/p>\n<p>So we wrote a version of what eventually got standardised, soon discovered that Ga\u0161per and Ben were working on a different paper for the exact same feature, we joined forces, and here we all are several years later.<\/p>\n<h3>Design<\/h3>\n<p>The key design principle we followed was that it should <em>do what you expect<\/em>. To achieve this, we touched as few places in the standard as we possibly could. Notably, we didn&#8217;t touch overload resolution rules or template deduction rules, and name resolution was only changed a little bit (as a treat).<\/p>\n<p>As such, say we have a type like so:<\/p>\n<pre><code class=\"language-cpp\">struct cat {\r\n    template &lt;class Self&gt;\r\n    void lick_paw(this Self&amp;&amp; self);\r\n};<\/code><\/pre>\n<p>The template parameter <code>Self<\/code> will be deduced based on all of the same template deduction rules you&#8217;re already familiar with. There&#8217;s no additional magic. You don&#8217;t have to use the names <code>Self<\/code> and <code>self<\/code>, but I think they&#8217;re the clearest options, and this follows what several other programming languages do.<\/p>\n<pre><code class=\"language-cpp\">cat marshmallow;\r\nmarshmallow.lick_paw();                         \/\/Self = cat&amp;\r\n\r\nconst cat marshmallow_but_stubborn;\r\nmarshmallow_but_stubborn.lick_paw();            \/\/Self = const cat&amp;\r\n\r\nstd::move(marshmallow).lick_paw();              \/\/Self = cat\r\nstd::move(marshmallow_but_stubborn).lick_paw(); \/\/Self = const cat<\/code><\/pre>\n<p>One name resolution change is that inside such a member function, you are not allowed to explicitly or implicitly refer to <code>this<\/code>.<\/p>\n<pre><code class=\"language-cpp\">struct cat {\r\n    std::string name;\r\n\r\n    void print_name(this const cat&amp; self) {\r\n        std::cout &lt;&lt; name;       \/\/invalid\r\n        std::cout &lt;&lt; this-&gt;name; \/\/also invalid\r\n        std::cout &lt;&lt; self.name;  \/\/all good\r\n    }\r\n};<\/code><\/pre>\n<h2>Use Cases<\/h2>\n<p>For the rest of this post, we&#8217;ll look at all the different uses of this feature (at least the ones discovered so far that I know of!) Many of these examples were taken straight from the paper.<\/p>\n<h3>De-duplication\/quadruplication<\/h3>\n<p>We&#8217;ve already seen how the feature can be applied to a type such as <code>optional<\/code> to avoid having to write four overloads of the same function.<\/p>\n<p>Note also that this lowers the burden on initial implementation and maintenance of dealing with rvalue member functions. Quite often developers will write only <code>const<\/code> and non-<code>const<\/code> overloads for member functions, since in many cases we don&#8217;t really want to write another two whole functions just to deal with rvalues. With deduced qualifiers on <code>this<\/code>, we get the rvalue versions for free: we just need to write <code>std::forward<\/code> in the right places to get the runtime performance gains which come with avoiding unnecessary copies:<\/p>\n<pre><code class=\"language-cpp\">class cat {\r\n    toy held_toy_;\r\n\r\npublic:\r\n    \/\/Before explicit object parameters\r\n    toy&amp; get_held_toy() { return held_toy_; }\r\n    const toy&amp; get_held_toy() const { return held_toy_; }\r\n\r\n    \/\/After\r\n    template &lt;class Self&gt;\r\n    auto&amp;&amp; get_held_toy(this Self&amp;&amp; self) {\r\n        return self.held_toy_;\r\n    }\r\n\r\n    \/\/After + forwarding\r\n    template &lt;class Self&gt;\r\n    auto&amp;&amp; get_held_toy(this Self&amp;&amp; self) {\r\n        return std::forward&lt;Self&gt;(self).held_toy_;\r\n    }\r\n};<\/code><\/pre>\n<p>Of course for a simple getter like this, whether or not this change is worth it for your specific use case is up to you. But for more complex functions, or cases where you are dealing with large objects which you want to avoid copying, explicit object parameters make this much easier to handle.<\/p>\n<h3>CRTP<\/h3>\n<p>The Curiously Recurring Template Pattern (CRTP) is a form of compile-time polymorphism which allows you to extend types with common pieces of functionality without paying the runtime costs of virtual functions. This is sometimes referred to as <em>mixins<\/em> (this isn&#8217;t <em>all<\/em> the CRTP can be used for, but it is the most common use). For example, we could write a type <code>add_postfix_increment<\/code> which can be mixed in to another type in order to define postfix increment in terms of prefix increment:<\/p>\n<pre><code class=\"language-cpp\">template &lt;typename Derived&gt;\r\nstruct add_postfix_increment {\r\n    Derived operator++(int) {\r\n        auto&amp; self = static_cast&lt;Derived&amp;&gt;(*this);\r\n\r\n        Derived tmp(self);\r\n        ++self;\r\n        return tmp;\r\n    }\r\n};\r\n\r\nstruct some_type : add_postfix_increment&lt;some_type&gt; {\r\n    \/\/ Prefix increment, which the postfix one is implemented in terms of\r\n    some_type&amp; operator++();\r\n};<\/code><\/pre>\n<p>Templating a base class on its derived cast and <code>static_cast<\/code>ing <code>this<\/code> inside the function can be a bit arcane, and the problem gets worse when you have multiple levels of CRTP. With explicit object parameters, since we didn&#8217;t change template deduction rules, <em>the type of the explicit object parameter can be deduced to a derived type<\/em>. More concretely:<\/p>\n<pre><code class=\"language-cpp\">struct base {\r\n    template &lt;class Self&gt;\r\n    void f(this Self&amp;&amp; self);\r\n};\r\n\r\nstruct derived : base {};\r\n\r\nint main() {\r\n    derived my_derived;\r\n    my_derived.f();\r\n}<\/code><\/pre>\n<p>In the call <code>my_derived.f()<\/code>, the type of <code>Self<\/code> inside <code>f<\/code> is <code>derived&amp;<\/code>, <em>not<\/em> <code>base&amp;<\/code>.<\/p>\n<p>This means that we can define the above CRTP example like so:<\/p>\n<pre><code class=\"language-cpp\">struct add_postfix_increment {\r\n    template &lt;typename Self&gt;\r\n    auto operator++(this Self&amp;&amp; self, int) {\r\n        auto tmp = self;\r\n        ++self;\r\n        return tmp;\r\n    }\r\n};\r\n\r\nstruct some_type : add_postfix_increment {\r\n    \/\/ Prefix increment, which the postfix one is implemented in terms of\r\n    some_type&amp; operator++();\r\n};<\/code><\/pre>\n<p>Note that now <code>add_postfix_increment<\/code> is not a template. Instead, we&#8217;ve moved the customisation to the postfix <code>operator++<\/code>. This means we don&#8217;t need to pass <code>some_type<\/code> as a template argument anywhere: everything &#8220;just works&#8221;.<\/p>\n<h3>Forwarding out of lambdas<\/h3>\n<p>Copying captured values out of a closure is simple: we can just pass around the object as usual. Moving captured values out of a closure is also simple: we can just call <code>std::move<\/code> on it. A problem occurs when we need to perfect-forward a captured value based on whether the closure is an lvalue or rvalue.<\/p>\n<p>One use case I stole from <a href=\"https:\/\/wg21.link\/p2445\">P2445<\/a> is for lambdas which can be used in both &#8220;retry&#8221; and &#8220;try or fail&#8221; contexts:<\/p>\n<pre><code class=\"language-cpp\">auto callback = [m=get_message(), &amp;scheduler]() -&gt; bool {\r\n    return scheduler.submit(m);\r\n};\r\ncallback(); \/\/ retry(callback)\r\nstd::move(callback)(); \/\/ try-or-fail(rvalue)<\/code><\/pre>\n<p>The question here is: how do we forward <code>m<\/code> based on the value category of the closure? Explicit object parameters give us the answer. Since a lambda generates a class with an <code>operator()<\/code> member function of the given signature, all the machinary I&#8217;ve just explained works for lambdas too.<\/p>\n<pre><code class=\"language-cpp\">auto closure = [](this auto&amp;&amp; self) {\r\n    \/\/can use self inside the lambda\r\n};<\/code><\/pre>\n<p>This means we can perfect-forward based on the value category of the closure inside the lambda. P2445 gives a <code>std::forward_like<\/code> helper, which forwards some expression based on the value category of another:<\/p>\n<pre><code class=\"language-cpp\">auto callback = [m=get_message(), &amp;scheduler](this auto &amp;&amp;self) -&gt; bool {\r\n    return scheduler.submit(std::forward_like&lt;decltype(self)&gt;(m));\r\n};<\/code><\/pre>\n<p>Now our original use case works, and the captured object will be copied or moved depending on how we use the closure.<\/p>\n<h3>Recursive lambdas<\/h3>\n<p>Since we now have the ability to name the closure object in a lambda&#8217;s parameter list, this allows us to do recursive lambdas! As above:<\/p>\n<pre><code class=\"language-cpp\">auto closure = [](this auto&amp;&amp; self) {\r\n    self(); \/\/just call ourself until the stack overflows\r\n};<\/code><\/pre>\n<p>There are more useful uses for this than just overflowing stacks, though. Consider, for example, the ability to do visitation of recursive data structures without having to define additional types or functions? Given the following definition of a binary tree:<\/p>\n<pre><code class=\"language-cpp\">struct Leaf { };\r\nstruct Node;\r\nusing Tree = std::variant&lt;Leaf, Node*&gt;;\r\nstruct Node {\r\n    Tree left;\r\n    Tree right;\r\n};<\/code><\/pre>\n<p>We can count the number of leaves like so:<\/p>\n<pre><code class=\"language-cpp\">int num_leaves(Tree const&amp; tree) {\r\n    return std::visit(overload( \/\/see below\r\n        [](Leaf const&amp;) { return 1; },                       \r\n        [](this auto const&amp; self, Node* n) -&gt; int {              \r\n            return std::visit(self, n-&gt;left) + std::visit(self, n-&gt;right); \r\n        }\r\n    ), tree);\r\n}<\/code><\/pre>\n<p><code>overload<\/code> here is some facility to create an overload set from multiple lambdas, and is commonly used for <code>variant<\/code> visitation. See <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/variant\/visit\">cppreference<\/a>, for example.<\/p>\n<p>This counts the number of leaves in the tree through recursion. For each function call in the call graph, if the current is a <code>Leaf<\/code>, it returns <code>1<\/code>. Otherwise, the overloaded closure calls itself through <code>self<\/code> and recurses, adding together the leaf counts for the left and right subtrees.<\/p>\n<h3>Pass <code>this<\/code> by value<\/h3>\n<p>Since we can define the qualifiers of the now-explicit object parameter, we can choose to take it by value rather than by reference. For small objects, this can give us better runtime performance. In case you&#8217;re not familiar with how this affects code generation, here&#8217;s an example.<\/p>\n<p>Say we have this code, using regular old implicit object parameters:<\/p>\n<pre><code class=\"language-cpp\">struct just_a_little_guy {\r\n    int how_smol;\r\n    int uwu();\r\n};\r\n\r\nint main() {\r\n    just_a_little_guy tiny_tim{42};\r\n    return tiny_tim.uwu();\r\n}<\/code><\/pre>\n<p>MSVC generates the following assembly:<\/p>\n<pre><code class=\"language-asm\">sub     rsp, 40                           \r\nlea     rcx, QWORD PTR tiny_tim$[rsp]\r\nmov     DWORD PTR tiny_tim$[rsp], 42     \r\ncall    int just_a_little_guy::uwu(void)  \r\nadd     rsp, 40                            \r\nret     0<\/code><\/pre>\n<p>I&#8217;ll walk through this line-by-line.<\/p>\n<ul>\n<li><code>sub rsp, 40<\/code> allocates 40 bytes on the stack. This is 4 bytes to hold the <code>int<\/code> member of <code>tiny_tim<\/code>, 32 bytes of <a href=\"https:\/\/stackoverflow.com\/questions\/30190132\/what-is-the-shadow-space-in-x64-assembly\"><em>shadow space<\/em>\u00a0<\/a>for <code>uwu<\/code> to use, and 4 bytes of padding.<\/li>\n<li>The <code>lea<\/code> instruction loads the address of the <code>tiny_tim<\/code> variable into the <code>rcx<\/code> register, which is where <code>uwu<\/code> is expecting the implicit object parameter (due to the <a href=\"https:\/\/docs.microsoft.com\/cpp\/build\/x64-calling-convention?view=msvc-170\">calling conventions<\/a> used).<\/li>\n<li>The <code>mov<\/code> stores <code>42<\/code> into the <code>int<\/code> member of <code>tiny_tim<\/code>.<\/li>\n<li>We then call the <code>uwu<\/code> function.<\/li>\n<li>Finally we de-allocate the space we allocated on the stack before and return.<\/li>\n<\/ul>\n<p>What happens if we instead specify <code>uwu<\/code> to take its object parameter by value, like this?<\/p>\n<pre><code class=\"language-cpp\">struct just_a_little_guy {\r\n    int how_smol;\r\n    int uwu(this just_a_little_guy);\r\n};<\/code><\/pre>\n<p>In that case, the following code is generated:<\/p>\n<pre><code class=\"language-asm\">mov     ecx, 42                           \r\njmp     static int just_a_little_guy::uwu(this just_a_little_guy) <\/code><\/pre>\n<p>We just move <code>42<\/code> into the relevant register and jump (<code>jmp<\/code>) to the <code>uwu<\/code> function. Since we&#8217;re not passing by-reference we don&#8217;t need to allocate anything on the stack. Since we&#8217;re not allocating on the stack we don&#8217;t need to de-allocate at the end of the function. Since we don&#8217;t need to deallocate at the end of the function we can just jump straight to <code>uwu<\/code> rather than jumping there and then back into this function when it returns, using <code>call<\/code>.<\/p>\n<p>These are the kinds of optimisations which can prevent &#8220;death by a thousand cuts&#8221; where you take small performance hits over and over and over, resulting in slower runtimes that are hard to find the root cause of.<\/p>\n<h3>SFINAE-unfriendly callables<\/h3>\n<p>This issue is a bit more esoteric, but does actually happen in real code (I know because I got a bug report on my extended implementation of <code>std::optional<\/code> which hit this exact issue in production). Given a member function of <code>optional<\/code> called <code>transform<\/code>, which calls the given function on the stored value only if there is one, the problem looks like this:<\/p>\n<pre><code class=\"language-cpp\">struct oh_no {\r\n    void non_const();\r\n};\r\n\r\ntl::optional&lt;oh_no&gt; o;\r\no.transform([](auto&amp;&amp; x) { x.non_const(); }); \/\/does not compile<\/code><\/pre>\n<p>The error which MSVC gives for this looks like:<\/p>\n<blockquote><p>error C2662: &#8216;void oh_no::non_const(void)&#8217;: cannot convert &#8216;this&#8217; pointer from &#8216;const oh_no&#8217; to &#8216;oh_no &amp;&#8217;<\/p><\/blockquote>\n<p>So it&#8217;s trying to pass a <code>const oh_no<\/code> as the implicit object parameter to <code>non_const<\/code>, which doesn&#8217;t work. But where did that <code>const oh_no<\/code> come from? The answer is inside the implementation of <code>optional<\/code> itself. Here is a deliberately stripped-down version:<\/p>\n<pre><code class=\"language-cpp\">template &lt;class T&gt;\r\nstruct optional {\r\n    T t;\r\n\r\n    template &lt;class F&gt;\r\n    auto transform(F&amp;&amp; f) -&gt; std::invoke_result_t&lt;F&amp;&amp;, T&amp;&gt;;\r\n\r\n    template &lt;class F&gt;\r\n    auto transform(F&amp;&amp; f) const -&gt; std::invoke_result_t&lt;F&amp;&amp;, const T&amp;&amp;&gt;;\r\n};<\/code><\/pre>\n<p>Those <code>std::invoke_result_t<\/code>s are there to make <code>transform<\/code> <a href=\"https:\/\/stackoverflow.com\/questions\/35033306\/what-does-it-mean-when-one-says-something-is-sfinae-friendly\">SFINAE-friendly<\/a>. This basically means that you can check whether a call to <code>transform<\/code> would compile and, if it wouldn&#8217;t, do something else instead of just aborting the entire compilation. However, there&#8217;s a bit of a hole in the language here.<\/p>\n<p>When doing overload resolution on <code>transform<\/code>, the compiler has to work out which of those two overloads is the best match given the types of the arguments. In order to do so, it has to instantiate the declarations of both the <code>const<\/code> and non-<code>const<\/code> overloads. If you pass an invocable to <code>transform<\/code> which is not <em>itself<\/em> SFINAE-friendly, and isn&#8217;t valid for a <code>const<\/code> qualified implicit object (which is the case with my example) then instantiating the declaration of the <code>const<\/code> member function will be a hard compiler error. Oof.<\/p>\n<p>Explicit object parameters allow you to solve this problem because the cvref qualifiers are <em>deduced<\/em> from the expression you call the member function on: if you never call the function on a <code>const optional<\/code> then the compiler never has to try and instantiate that declaration. Given <code>std::copy_cvref_t<\/code> from <a href=\"https:\/\/wg21.link\/p1450\">P1450<\/a>:<\/p>\n<pre><code class=\"language-cpp\">template &lt;class T&gt;\r\nstruct optional {\r\n    T t;\r\n\r\n    template &lt;class Self, class F&gt;\r\n    auto transform(this Self&amp;&amp; self, F&amp;&amp; f) \r\n    -&gt; std::invoke_result_t&lt;F&amp;&amp;, std::copy_cvref_t&lt;Self, T&gt;&gt;;\r\n};<\/code><\/pre>\n<p>This allows the above example to compile while still allowing <code>transform<\/code> to be SFINAE-friendly.<\/p>\n<h2>Conclusion<\/h2>\n<p>I hope this has helped clarify the function and utility of explicit object parameters. You can try out the feature in <a href=\"https:\/\/visualstudio.microsoft.com\/vs\/features\/cplusplus\/\">Visual Studio version 17.2<\/a>. If you have any questions, comments, or issues with the feature, you can comment below, or reach us via email at <a href=\"mailto:visualcpp@microsoft.com\">visualcpp@microsoft.com<\/a> or via Twitter at <a href=\"https:\/\/twitter.com\/visualc\">@VisualC<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Find out how C++23&#8217;s Deducing this feature can help make your code better.<\/p>\n","protected":false},"author":706,"featured_media":30711,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,512],"tags":[],"class_list":["post-30707","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","category-general-cpp-series"],"acf":[],"blog_post_summary":"<p>Find out how C++23&#8217;s Deducing this feature can help make your code better.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/30707","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/706"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=30707"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/30707\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/30711"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=30707"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=30707"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=30707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}