
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>D2718R0: Wording for P2644R1 Fix for Range-based for Loop</title>

<style type="text/css">
body { color: #000000; background-color: #FFFFFF; max-width: 40em; }
del, .del { text-decoration: line-through; color: #8B0040; }
ins, .ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std, ul.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.std del, blockquote.std .del, ul.std del, ul.std .del { text-decoration: line-through;
  color: #000000; background-color: #FFCCCC;
  border: 1px solid #ECD7EC; }
blockquote.std ins, blockquote.std .ins, ul.std ins, ul.std .ins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFCCCC;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stdins { text-decoration: none;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding-left: 0.5em; padding-right: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

table.table { border-spacing: 2px; border-collapse: separate; }
.table * th, .table * td { border: 1px solid black; }

table.frontmatter { border: 0; border-spacing: 0px; border-collapse: collapse; margin: 0; width: 619px; }
.frontmatter * td, .frontmatter * th { padding: 0px; }
.frontmatter * th { font-weight: inherit; text-align: left; vertical-align: top; }

ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }

span.highlight { background-color: #7FDFFF }
span.grammar { font-family: sans-serif; font-style: italic; font-size: 83.3%; }
span.metavar { font-family: sans-serif; font-weight: bold; font-size: 83.3%; }

.nowrap { white-space: nowrap; }
.pre { white-space: pre; }

pre { font-family: inherit; }
code { font-style: normal !important; }

.subtitle { font-size: 80%; }

#xins1:checked ~ * ins { display: none; visibility: hidden }
#xins1:checked ~ * .inline-ins { display: none; visibility: hidden }
#xdel1:checked ~ * del { display: none; visibility: hidden }
</style>

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js"></script>
</head>

  <body>
<h1>Wording for P2644R1 Fix for Range-based for Loop</h1>
<table class="frontmatter"><tbody>
    <tr>
        <th>Document#:</th>
        <td>P2718R0</td>
    </tr>
    <tr>
        <th>Date:</th>
        <td>2022-11-11</td>
    </tr>
    <tr>
        <th>Project:</th>
        <td>ISO JTC1/SC22/WG21: Programming Language C++ </td>
    </tr>
    <tr>
        <th>Audience subgroup:</th>
        <td>Core</td>
    </tr>
    <tr>
        <th>Reply-to:</th>
        <td><span class="nowrap">Nicolai Josuttis</span> &lt;<a href="mailto:nico@josuttis.de">nico@josuttis.de</a>&gt;<br/>
<span class="nowrap">Joshua Berne</span> &lt;<a href="mailto:jberne4@bloomberg.net">jberne4@bloomberg.net</a>&gt;</td>
	</td>
    </tr>
</tbody></table>

<h2>Introduction</h2>
This contains the wording extracted from P2644R1 (Final Fix of Broken Range‐based for Loop) and then updated based on guidance from CWG November 10 and 11, 2022.
    
    
<h2>Proposed Wording</h2>

<p>The following is in reference to N4919.</p>

<div>
  <input type="checkbox" id="xins1" /><label for="xins1">Hide text inserted in-line</label>
  <input type="checkbox" id="xdel1" /><label for="xdel1">Hide text deleted in-line</label>

  <p>In subclause 6.7.7 [class.temporary], modify p5:</p>
  <blockquote class="std">
    <p>There are <del>three</del><ins>four</ins> contexts in which temporaries
      are destroyed at a different point than the end of the full-expression. ... </p>
  </blockquote>

  <p>In subclause 6.7.7 [class.temporary], add a paragraph after p6</p>
  <blockquote class="stdins">
    <p>The fourth context is when a temporary object other than a function parameter object
      is created in the <em>for-range-initializer</em> of a range-based for statement. If such a
      temporary object would otherwise be destroyed at the end of the <em>for-range-initializer</em>
      full-expression, the object persists for the lifetime of the reference initialized by the
      <em>for-range-initializer</em>.
    </p>
  </blockquote>

  <p> In subclause 6.7.7 [class.temporary], modify p7</p>
  <blockquote class="std">
    The destruction of a temporary whose lifetime is not extended <ins>beyond the full-expression
    in which it was created</ins><del>by being bound to a reference</del> is sequenced
    before the destruction of every temporary which is constructed earlier in the same full-expression. If the
    lifetime of two or more temporaries <ins>with lifetimes extending beyond the full-expressions in which they were created</ins>
    <del>to which references are bound</del> ends at the same point, these temporaries
    are destroyed at that point in the reverse order of the completion of their construction. In addition, the
    destruction of <ins>such</ins> temporaries <del>bound to references</del> shall take into account the ordering of destruction of objects
    with static, thread, or automatic storage duration (6.7.5.2, 6.7.5.3, 6.7.5.4); that is, if obj1 is an object with
    the same storage duration as the temporary and created before the temporary is created the temporary shall
    be destroyed before obj1 is destroyed; if obj2 is an object with the same storage duration as the temporary
    and created after the temporary is created the temporary shall be destroyed after obj2 is destroyed.
  </blockquote>
  
  <p>In subclause 8.6.5 [stmt.ranged] add before Example 1:</p>
  <blockquote class="stdins">
    <p>[ Note: The lifetime of some temporaries in the <em>for-range-initializer</em> is extended to cover the entire loop (6.7.7 [class.temporary]). --- end note ]
[Example:<pre><code>using T = std::list&lt;int&gt;;
const T& f1(const T& t) { return t; }
const T& f2(T t)        { return t; }
T g();
void foo() {
  for (auto e : f1(g())) {}  // OK, lifetime of return value of g() extended
  for (auto e : f2(g())) {}  // undefined behavior
}
</code></pre>
--- end example]</p>
  </blockquote>

  <p>Add a new section in Annex C:</p>
  <blockquote class="stdins">
<p><b>Affected subclause:</b> 8.6.5 [stmt.ranged]</p>
<p><b>Change:</b> The lifetime of temporary objects in the <em>for‐range‐initializer</em> is
  extended until the end of the loop (6.7.7 [class.temporary]).</p>
<p><b>Rationale:</b> Improve usability of the range-based for loop.</p>
<p><b>Effect on original feature:</b> Destructors of some temporary objects are invoked later.<p>
<p> [Example1:</p><!--
--><pre><code>void f()
{
    std::vector&lt;int&gt; v = { 42, 17, 13 };
    std::mutex m;
    for (int x : static_cast&lt;void&gt;(std::lock_guard&lt;std::mutex&gt;(m)), v)  // lock released in C++ 2020
    {
	std::lock_guard&lt;std::mutex&gt; guard(m);  // OK in C++ 2020, now deadlocks
    }
}
</code></pre>
<p>--  end example]</p>
</blockquote>
	    
</div>
</body></html>
