<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
    <title>Deprecate implicit capture of this via [=]</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; }

      .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; }

      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; }

      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: 2018-04-02</p>
      <address>Thomas K&ouml;ppe &lt;<a href="mailto:tkoeppe@google.com">tkoeppe@google.com</a>&gt;</address>
      <p class="skip">ISO/IEC JTC 1/SC 22/WG 21 P0806R1</p>
      <p>To: CWG</p>
    </div>

    <h1>Deprecate implicit capture of <code>this</code> via <code>[=]</code></h1>

    <!-- fgrep -e "<h2 id=" deprecate_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="#future">Future directions</a></li>
      <li><a href="#compat">Compatibility, upgrade path, warnings</a></li>
    </ol>

    <h2 id="history">Revision history</h2>
    <ul>
      <li><a href="">P0806R0</a>: Initial proposal.</li>
      <li>P0806R1: Remove the <code>[&amp;]</code> part; only deprecate <code>[=]</code> now, as requested by EWG.
        Rebased on current working paper wording.</li>
    </ul>
    <p>
      <em>Historical note</em>: Revision 0 proposed to deprecate the implicit capture of <code>this</code>
      for both <code>[=]</code> and <code>[&amp;]</code> <em>capture-default</em>s. During discussion
      in Albuquerque, EWG wanted to retain <code>[&amp;]</code> as an idiomatic way to capture
      <code>this</code> and only supported the deprecation the case of <code>[=]</code>.
    </p>

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

    <p>We propose to deprecate the implicit capture of <code>this</code> in a lambda expression
      with a <em>capture-default</em> <code>[=]</code>. Users should explicitly use one of
      <code>[=, this]</code> or <code>[=, *this]</code>.</p>

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

      <thead>
        <tr><th>Before the proposal</th><th>With the proposal</th></tr>
      </thead>

      <tbody>
        <tr>
          <td><div class="code">struct Foo {
              &nbsp; int n = 0;
              &nbsp; void f(int a) {
              &nbsp; &nbsp; g(<span style="color: #A00; font-weight: bold;">[=]</span>(int k) { return n + a * k; });
              &nbsp; &nbsp; g([=, *this](int k) { return n + a * k; });
              &nbsp; &nbsp; g([&amp;, a](int k) { n += a * k; });
              &nbsp; }
              };</div></td>
          <td><div class="code">struct Foo {
              &nbsp; int n = 0;
              &nbsp; void f(int a) {
              &nbsp; &nbsp; g(<span style="color: #0A0; font-weight: bold;">[=, this]</span>(int k) { return n + a * k; });
              &nbsp; &nbsp; g([=, *this](int k) { return n + a * k; });
              &nbsp; &nbsp; g([&amp;, a](int k) { n += a * k; });
              &nbsp; }
              };</div></td>
        </tr>
      </tbody>
    </table>

    <h2 id="discussion">Discussion</h2>

    <p>There are two kinds of default capture in a lambda expression:</p>
    <ul>
      <li><code>[&amp;]</code>: names in the lambda body refer to the actual entities that they name.</li>
      <li><code>[=]</code>: names in the lambda body refer to local data members of the closure object that
        were copied from the entities in the surrounding scope.</li>
    </ul>

    <p>When the lambda expression occurs inside a non-static class member function, any name <code>foo</code>
      of a non-static class member is interpreted as <code>this-&gt;foo</code>, where <code>this</code> is now
      bound to a local data member of the closure object. This copy is initialised from the value of <code>this</code>
      of the surrounding class member function <em>for both kinds of default capture</em>.</p>

    <p>This situation is somewhat surprising and irregular. The semantics of capture-by-reference
      suggest that class members should refer directly to class members of the containing object.
      On the other hand, <code>this</code> is a pointer value, and it is clearly itself <em>copied</em>
      into the closure object. So whichever way one looks at the capture, one can rationalise for both
      <code>[&amp;]</code> and <code>[=]</code> that they cause a copy of <code>this</code> to be
      stored in the closure object. By contrast, neither capture default effects the capture of
      <code>[*this]</code>, which would copy the entire containing object into the closure object and
      rebind <code>this</code> to point to that copy.</p>

    <p>At this point, some historic background is helpful. The <code>this</code> keyword was
      introduced to C++ before references. At the time, C++ was translated into C, and the
      simple pointer semantics of <code>this</code> were convenient. If the entire feature set
      of references, value categories and classes had been designed together, <code>this</code>
      would have been an lvalue designating the object, and not a prvalue designating the
      address of the object. We can adopt this historic perspective by thinking of the fundamental
      object as &ldquo;<code>*this</code>&rdquo; rather than <code>this</code>. Let us consider
      how we might capture this object:</p>

    <ul>
      <li>Capture <code>*this</code> by value: <code>[*this]</code></li>
      <li>Capture <code>*this</code> by reference: hypothetically we would say
        &ldquo;<code>[&amp;*this]</code>&rdquo;; in C++ we say <code>[this]</code></li>
      <li>If the default capture is reference capture, the hypothetical &ldquo;<code>[&amp;, &amp;*this]</code>&rdquo;
        (in real C++: <code>[&amp;, this]</code>) is a redundant reference capture; <code>[&amp;, *this]</code> is
        a non-redundant value capture.</li>
      <li>If the default capture is value capture, the hypothetical &ldquo;<code>[=, &amp;*this]</code>&rdquo;
        (in real C++: <code>[=, this]</code>) is a non-redundant reference capture; <code>[=, *this]</code> is
        a (redundant-looking) value capture.</li>
    </ul>

    <p>In C++14, the fact that both default captures captured the <code>this</code> pointer was
      perhaps peculiar, but unambiguous. But C++17 added genuine value-capture of the containing
      object via <code>[*this]</code>, so that it is now more surprising that <code>[=]</code>
      means <code>[=, this]</code> and not <code>[=, *this]</code>. In other words, one default
      capture (<code>[&amp;]</code>) captures <code>*this</code> in the way that would be redundant
      when spelled out, but the other capture (<code>[=]</code>) captures it in the non-redundant
      way.</p>

    <p>This inconsistency in defaults is confusing. Users may well know that there <em>exists</em>
      an inconsistency, but it is much harder to know which way round the inconsistency goes.
      For this reason, we propose that users should never rely on implicit capture of <code>*this</code>
      via a <code>[=]</code>-<em>capture-default</em>. (The implicit capture of <code>*this</code> via
      <code>[&amp;]</code> continues to be idiomatic. An earlier revision of this paper also proposed
      its deprecation.)</p>
    <ul>
      <li><code>[=]</code> &rarr; <code>[=, &nbsp;this]</code>: local variables by value, class members by reference</li>
      <li><code>[=]</code> &rarr; <code>[=, *this]</code>: everything by value</li>
      <li><code>[&amp;]</code> &rarr; <code>[&amp;, &nbsp;this]</code>: everything by reference</li>
      <li><code>[&amp;]</code> &rarr; <code>[&amp;, *this]</code>: (this would be unusual)</li>
    </ul>

    <p>Beyond this proposal, we recommend that as a matter of style, code should only ever capture
      <code>*this</code> explicitly, even in the presence of <em>capture-default</em>s.</p>

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

    <p>Append a sentence to [8.4.5.2 expr.prim.lambda.capture]p7:</p>
    <div class="modify">
      [&hellip;] If an expression potentially references a local entity
      within a declarative region in which it is odr-usable,
      and the expression would be potentially evaluated
      if the effect of any enclosing <code>typeid</code> expressions ([expr.typeid, 8.5.1.8]) were ignored,
      the entity is said to be <em>implicitly captured</em>
      by each intervening <em>lambda-expression</em> with an associated
      <em>capture-default</em> that does not explicitly capture it.
      <ins>The implicit capture of <code>*this</code> when the <em>capture-default</em>
      is <code>=</code> is deprecated; see [depr.capture.this, D.?].</ins>
      [<em>Example</em>: [&hellip;]
    </div>

    <p>Insert a new section [D, depr], between the current [D.3, depr.except.spec] and [D.4, depr.cpp.headers].</p>
    <div class="insert">
      <h3><ins>D.? Implicit capture of <code>*this</code> by reference [depr.capture.this]</ins></h3>
      <p><ins>For compatibility with prior C++ International Standards, a lambda expression with
        <em>capture-default</em> <code>=</code> ([8.4.5.2, expr.prim.lambda.capture])
        can capture <code>*this</code> by reference implicitly.</ins></p>
    </div>

    <h2 id="future">Future directions</h2>

    <p>The obvious next step would be to make the implicit capture of <code>*this</code> ill-formed
      in a [=]-capture.
      This could only happen post-C++20, since valid C++17 code must first upgrade to C++20 by
      changing <code>[=]</code> to <code>[=, this]</code>, which is ill-formed in C++17 (added by
      <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0409r2.html">P0409R2</a>).
      The meaning of <code>[=]</code> could then be changed again in the farther future. Such a
      change would presumably affect a large amount of use cases, but the upgrade path is
      straight-forward. Alternatively, the feature could simply remain deprecated to guide
      users and authors of style guides to avoid implicit capture of <code>*this</code> in new code.</p>

    <h2 id="compat">Compatibility, upgrade path, warnings</h2>

    <p>Let us briefly examine the upgrade path and compiler warnings that would likely result
      from this proposed change, in the spirit
      of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0684r2.pdf">P0684R2</a>.
      The change does not break otherwise valid C++20 code, and the earliest revision in which a
      breakage from C++17 could appear is C++23. Therefore compilers for the current standard
      (C++17) need not emit <em>any</em> warning, but at best it would be a &ldquo;future
      deprecation&rdquo; warning rather than a &ldquo;future breakage&rdquo; warning. In C++20
      conformance mode, compilers may reasonably emit a deprecation warning by default, or they
      could defer any warnings to the &ldquo;future breakage&rdquo; kind if and when a proposal
      for a breaking change is accepted. The replacement <code>[=, this]</code> for the
      deprecated <code>[=]</code> is ill-formed in C++17 and only available in C++20 as
      of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0409r2.html">P0409R2</a>.</p>

  </body>
</html>
