<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
    <title>Capture *this with initializer</title>
    <style type="text/css">
      html { margin: 0; padding: 0; color: black; background-color: white; }
      body { padding: 2em; font-size: medium; font-family: "DejaVu Serif", serif; line-height: 150%; }
      code { font-family: "DejaVu Sans Mono", monospace; color: #006; }

      h1, h2, h3 { margin: 1.5em 0 .75em 0; line-height: 125%; }

      div.code { white-space: pre-line; font-family: "DejaVu Sans Mono", monospace;
                 border: thin solid #E0E0E0; background-color: #F8F8F8; padding: 1em;
                 border-radius: 4px; }

      div.strictpre { white-space: pre; }

      sup, sub { line-height: 0; }

      .docinfo { float: right; }
      .docinfo p { margin: 0; text-align:right; }
      .docinfo address { font-style: normal; }

      table { border-top: 2px solid black; border-bottom: 2px solid black; border-collapse: collapse; margin: 3em auto; }
      thead th { border-bottom: 2px solid black; }
      th, td { text-align: left; padding: 1ex 1ex 1ex 5em; }
      th:first-child, td:first-child { padding-left: 1ex; }

      .quote { display: inline-block; clear: both; margin-left: 1ex;
                 border: thin solid #E0E0E0; background-color: #F8F8F8; padding: 1ex; }

      .modify { border-left: thick solid #999; border-right: thick solid #999; padding: 0 1em; }
      .insert { border-left: thick solid #0A0; border-right: thick solid #0A0; padding: 0 1em; }
      .comment { color: #456; }

      p.skip { margin-top: 1em; }

      ins { color: #090; }
      del { color: #A00; }
      ins code, del code { color: inherit; }
    </style>
  </head>
  <body>
    <div class="docinfo">
      <p>Date: 2017-06-18</p>
      <address>Thomas K&ouml;ppe &lt;<a href="mailto:tkoeppe@google.com">tkoeppe@google.com</a>&gt;</address>
      <p class="skip">ISO/IEC JTC1 SC22 WG21 P0637R0</p>
      <p>To: EWG</p>
    </div>

    <h1>Capture <code>*this</code> with initializer</h1>

    <!-- fgrep -e "<h2 id=" capture_this.html | sed -e 's/.*id="\(.*\)">\(.*\)<\/h2>/<li><a href="#\1">\2<\/a><\/li>/g' -->
    <h2>Contents</h2>
    <ol>
      <li><a href="#history">Revision history</a></li>
      <li><a href="#summary">Summary</a></li>
      <li><a href="#discussion">Discussion</a></li>
      <li><a href="#wording">Proposed wording</a></li>
      <li><a href="#nonprop">Non-proposal</a></li>
    </ol>

    <h2 id="history">Revision history</h2>
    <ul>
      <li>P0637R0: Initial proposal.</li>
    </ul>

    <h2 id="summary">Summary</h2>

    <p>We propose to allow the lambda by-value capture of <code>*this</code> to rebind
      <code>this</code> to arbitrary objects:
      <code>[*this <strong style="color: #080;">= std::move(x)</strong>](){}</code></p>

    <table>
      <col style="width: 42em">
      <col style="width: 47em">

      <thead>
        <tr><th>Ordinary capture</th><th><code>*this</code> capture</th></tr>
      </thead>

      <tbody>
        <tr>
          <td><div class="code" style="color: #666">struct X {
              &nbsp; void f(int n);

              &nbsp; void g() {
              &nbsp; &nbsp; // Capture copy of current object
              &nbsp; &nbsp; <span style="color: #A00;">X that = *this; [that] &nbsp; (int n) { that.f(n); } &nbsp; <span style="color: #666;">// C++11</span>
              &nbsp; &nbsp; [self = *this] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (int n) { self.f(n); }</span> &nbsp; <span style="color: #666;">// C++14</span>
              &nbsp; }

              &nbsp; void h() {
              &nbsp; &nbsp; // Capture copy of different object
              &nbsp; &nbsp; <span style="color: #A00;">X that = X(); [that] &nbsp; &nbsp; (int n) { that.f(n); } &nbsp; <span style="color: #666;">// C++11</span>
              &nbsp; &nbsp; [self = X()] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (int n) { self.f(n); } &nbsp; <span style="color: #666;">// C++14</span>
              &nbsp; &nbsp; [self = std::move(*this)](int n) { self.f(n); }</span> &nbsp; <span style="color: #666;">// C++14</span>
              &nbsp; }
              };</div></td>
          <td><div class="code" style="color: #666">struct X {
              &nbsp; void f(int n);

              &nbsp; void g() {
              &nbsp; &nbsp; // Capture copy of current object

              &nbsp; &nbsp; <span style="color: #040;">[*this] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; &nbsp; &nbsp; &nbsp; (int n) { f(n); }</span> &nbsp; <span style="color: #666;">// C++17</span>
              &nbsp; }

              &nbsp; void h() {
              &nbsp; &nbsp; // Capture copy of different object

              &nbsp; &nbsp; <span style="color: #080;">[*this = X()] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (int n) { f(n); }</span> &nbsp; <span style="color: #080; font-weight: bold;">// New!</span>
              &nbsp; &nbsp; <span style="color: #080;">[*this = std::move(*this)](int n) { f(n); }</span> &nbsp; <span style="color: #080; font-weight: bold;">// New!</span>
              &nbsp; }
              };</div></td>
        </tr>
      </tbody>
    </table>

    <p>In particular, this feature &ldquo;adds move semantics to C++17&rsquo;s value-capture
      of <code>*this</code>&rdquo;. Situations that motivated value-capture (see
      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r3.html">P0018R3</a>),
      such as asynchronous dispatch, arise when then current class instance does not outlive the
      desired lambda, in which case the lambda needs a copy of the current instance. However, in
      typical cases where only one such &ldquo;asynchronous hand-off&rdquo; happens, a copy is not
      actually required, and it suffices to <em>move</em> the instance data along into the lambda.
    </p>
    
    <h2 id="discussion">Discussion</h2>

    <p>C++11 introduced lambda expressions that could capture named entities from their
      environment by value. C++14 extended this facility to allow capture by value of
      arbitary expressions. C++17 introduced the ability for lambda expressions that appear
      in the definition of a non-static class member function to rebind the meaning of
      the <code>this</code> keyword inside the lambda body: The rebound <code>this</code>
      would refer to a private copy of the class instance that is captured by the lambda
      expression and stored within the closure object (P0018R3):</p>

    <div class="code">struct X {
      &nbsp; void g(int n);
      &nbsp; void f() {
      &nbsp; &nbsp; <span style="color: #A00;">auto h = [self = *this](int n) { self.g(n); };</span>
      &nbsp; &nbsp; // Same as:
      &nbsp; &nbsp; <span style="color: #080;">auto h = [*this](int n) { this-&gt;g(n); };</span> // &ldquo;this == &amp;__self&rdquo; for a secret value __self
      &nbsp; }
      };</div>

    <p>The extension provided by P0018R3 looks simple, but is conceptually profound:
      For the first time, the meaning of <code>this</code> can vary inside a single
      class&rsquo;s scope and be rebound by the user. Once we are comfortable with this
      situation, it is only natural to ask for ability to rebind <code>this</code> to
      <em>any</em> captured value of the right type. Just as C++14 added value capture
      from expressions to C++11 value capture, we propose to add <code>*this</code> capture
      from expressions to C++17 <code>*this</code> capture.</p>

    <p>Unlike the <em>simple-capture</em> &ldquo;<code>*this</code>&rdquo;, which would be
      equivalent under this proposal to &ldquo;<code>*this = *this</code>&rdquo;, the
      <em>init-capture</em> form is not constrained to appear in a non-static class member,
      since it does not require a prototypical instance to copy from, and we can allow it in
      static member functions just as well.</p>

    <p>Example:</p>

    <div class="code">struct X {
      &nbsp; std::unique_ptr&lt;int&gt; p_;
      &nbsp; void g(int n) const;

      &nbsp; auto f() &amp;&amp; {
      &nbsp; &nbsp; return [*this = std::move(*this)](int n) { g(n + *p_); }; &nbsp; // move the current object
      &nbsp; }

      &nbsp; void f(X x) {
      &nbsp; &nbsp; return [*this = std::move(x), m = *p_]() { g(m + *p_); }; &nbsp; // move some other object
      &nbsp; }

      &nbsp; static auto CallMyX(int m) {
      &nbsp; &nbsp; return [*this = X{std::make_unique&lt;int&gt;(m)}](int n) { g(n + *p_); } &nbsp; // use a newly created instance
      &nbsp; }
      };</div>

    <h2 id="wording">Proposed wording</h2>

    <p>Change 8.1.2 [expr.prim.this] paragraph 2 as follows.</p>

    <div class="modify">
      <p>[&hellip;] It shall not appear before the optional <em>cv-qualifier-seq</em>
        and it shall not appear within the declaration of a static member function
        (although its type and value category are defined within a static member
        function as they are within a non-static member function)<ins>, except in the
        body of a lambda expression that captures <code>*this</code> [<em>Note</em>:
        necessarily via init-capture &ndash; <em>end note</em>]</ins>.
        [<em>Note</em>: This is because [&hellip;]</p>
    </div>

    <p>Change the grammar in 8.1.5.2 [expr.prim.lambda.capture] as follows.</p>

    <div class="modify">
      <em>init-capture</em>:<br>
      &nbsp; &nbsp; <em>identifier</em> <em>initializer</em><br>
      &nbsp; &nbsp; <code>&amp;</code> <em>identifier</em> <em>initializer</em><br>
      &nbsp; &nbsp; <ins><code>* this</code> <em>initializer</em></ins></div>

    <p>Change paragraph 6 as follows.</p>
    <div class="modify">
      <p>An <em>init-capture</em> <ins>that is not <code>* this</code> <em>initializer</em></ins>
        behaves as if it declares and explicitly captures a variable of the form &ldquo;<code>auto</code>
        <em>init-capture</em> <code>;</code>&rdquo;<ins>. An <em>init-capture</em> <code>* this</code> <em>initializer</em>
        behaves as if it declares and explicitly captures a variable of the form &ldquo;<code>auto __this</code>
        <em>initializer</em> <code>;</code>&rdquo;. The</ins>
        <del>whose</del> declarative region <ins>of this variable</ins> is the
        lambda-expression&rsquo;s compound-statement, except that:</p>
      <ul>
        <li>if the capture is by copy (see below), the non-static data member declared for the capture and the
          variable are treated as two different ways of referring to the same object, which has the lifetime of the
          non-static data member, and no additional copy and destruction is performed, and</li>
        <li>if the capture is by reference, the variable&rsquo;s lifetime ends when the closure object&rsquo;s lifetime ends.</li>
      </ul>
      <p>[<em>Note</em>: This enables an init-capture like &ldquo;<code>x = std::move(x)</code>&rdquo;;
        the second &ldquo;<code>x</code>&rdquo; must bind to a declaration in the surrounding context.
        &ndash;&nbsp;<em>end note</em>]</p>
    </div>

    <p>Change paragraph 8 as follows.</p>
    <div class="modify">
      <p>[&hellip;] If <code>*this</code> is captured by a local lambda
        expression, its nearest enclosing function shall be a non-static member function.
        <ins>If <code>__this</code> is captured, the nearest enclosing function shall be a
        member function and the type of <code>__this</code> shall be the
        same as that of the enclosing class.</ins> If a lambda-expression [&hellip;]</p>
    </div>

    <p>Change paragraph 11 as follows.</p>
    <div class="modify">
      <p>[&hellip;] If <code>*this</code> is captured by copy <ins>or <code>__this</code> is captured</ins>,
        each odr-use of <code>this</code> is transformed<ins>, respectively,</ins> into a pointer to the
        corresponding unnamed data member <ins>or to the <code>__this</code> member</ins> of the closure
        type, cast (8.4) to the type of <code>this</code>. [&hellip;]</p>
    </div>

    <h2 id="nonprop">Non-proposal</h2>

    <p>This proposal is limited to value capture of <code>*this</code>. A natural question is why we would
      not also allow <em>reference</em> capture of <code>*this</code> to rebind <code>this</code>. The
      reason is that such an extension seems much more difficult, and it seems less useful to the author.</p>

    <p>Let us briefly examine the problems. A reference <em>init-capture</em> currently starts
      with <code>&amp;</code>. The natural syntax for reference <em>init-capture</em> of <code>*this</code>
      would be &ldquo;<code>[&amp;*this = x]</code>&rdquo;. This syntax may look surprising at first
      sight, but it is natural if we think of <code>*this</code> as the fundamental object. But then we
      would end up with two separate syntaxes, <code>[this]</code> for the <em>simple-capture</em>
      and <code>[&amp;*this = x]</code> for the <em>init-capture</em>, and <code>[this]</code> would
      be equivalent to <code>[&amp;*this = *this]</code>. If we were tempted to replace <code>&amp;*this</code>
      with just <code>this</code> for backwards &ldquo;consistency&rdquo;, we would end up with paradoxical syntax
      like <code>[this = *this]</code>. Alteratively, or additionally, we could consider a separate pointer capture
      <code>[this = &amp;x]</code> that reseats <code>this</code>. We believe that such extensions should be
      discussed in depth in a separate proposal.</p>
  </body>
</html>
