<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3077: (push|emplace)_back should invalidate the end iterator</title>
<meta property="og:title" content="Issue 3077: (push|emplace)_back should invalidate the end iterator">
<meta property="og:description" content="C++ library issue. Status: C++20">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3077.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++20">C++20</a> status.</em></p>
<h3 id="3077"><a href="lwg-defects.html#3077">3077</a>. <code>(push|emplace)_back</code> should invalidate the <code>end</code> iterator</h3>
<p><b>Section:</b> 23.3.13.5 <a href="https://wg21.link/vector.modifiers">[vector.modifiers]</a> <b>Status:</b> <a href="lwg-active.html#C++20">C++20</a>
 <b>Submitter:</b> Casey Carter <b>Opened:</b> 2018-03-10 <b>Last modified:</b> 2021-02-25</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#vector.modifiers">issues</a> in [vector.modifiers].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++20">C++20</a> status.</p>
<p><b>Discussion:</b></p>
<p>
23.3.13.5 <a href="https://wg21.link/vector.modifiers">[vector.modifiers]</a> paragraph 1 specifies that <code>emplace_back</code>
and <code>push_back</code> do not invalidate iterators before the insertion point when
reallocation is unnecessary:
<blockquote>
<i>Remarks:</i> Causes reallocation if the new size is greater than the old capacity.
Reallocation invalidates all the references, pointers, and iterators referring to
the elements in the sequence. If no reallocation happens, all the iterators and
references before the insertion point remain valid. [&hellip;]
</blockquote>
This statement is redundant, given the blanket wording in
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> paragraph 12:
<blockquote>
Unless otherwise specified (either explicitly or by defining a function in terms
of other functions), invoking a container member function or passing a container
as an argument to a library function shall not invalidate iterators to, or change
the values of, objects within that container.
</blockquote>
It seems that this second sentence (1) should be a note that reminds us that the
blanket wording applies here when no reallocation occurs, and/or (2) actually
intends to specify that iterators at and after the insertion point are invalidated.
</p>
<p>
Also, it seems intended that reallocation should invalidate the <code>end</code>
iterator as well.
</p>

<p><i>[2018-06-18 after reflector discussion]</i></p>

<p>Priority set to 3</p>
<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<ol>
<li>
<p>Edit 23.3.13.5 <a href="https://wg21.link/vector.modifiers">[vector.modifiers]</a> as indicated:</p>
<blockquote>
<p>
-1- <i>Remarks:</i> <ins>Invalidates the past-the-end iterator.</ins> Causes
reallocation if the new size is greater than the old capacity. Reallocation
invalidates all the references, pointers, and iterators referring to the elements
in the sequence. <ins>[<i>Note:</i></ins> If no reallocation happens, all the
iterators and references before the insertion point remain
valid.<ins>&mdash;<i>end note</i>]</ins> If an exception is thrown [&hellip;]
</p>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2018-11-28 Casey provides an updated P/R]</i></p>

Per discussion in the prioritization thread on the reflector.

<p><i>[2018-12-01 Status to Tentatively Ready after seven positive votes on the reflector.]</i></p>



<p id="res-3077"><b>Proposed resolution:</b></p>
<p>
This wording is relative to the post-San Diego working draft.
</p>

<ol>
<li>
<p>Change 27.4.3.5 <a href="https://wg21.link/string.capacity">[string.capacity]</a> as indicated:</p>
<blockquote>
<blockquote>
<pre>
void shrink_to_fit();
</pre>
</blockquote>
<p>
-11- <i>Effects:</i> <code>shrink_­to_­fit</code> is a non-binding request to reduce
<code>capacity()</code> to <code>size()</code>. [ <i>Note:</i> The request is
non-binding to allow latitude for implementation-specific optimizations.
&mdash; <i>end note</i> ] It does not increase <code>capacity()</code>, but may
reduce <code>capacity()</code> by causing reallocation.
</p><p>
-12- <i>Complexity:</i> <ins>If the size is not equal to the old capacity,</ins>
linear in the size of the sequence<ins>; otherwise constant</ins>.
</p><p>
-13- <i>Remarks:</i> Reallocation invalidates all the references, pointers, and
iterators referring to the elements in the sequence<ins>,</ins> as well as the
past-the-end iterator. <ins>[ <i>Note:</i></ins> If no reallocation happens,
they remain valid. <ins>&mdash; <i>end note</i> ]</ins>
</p>
</blockquote>
</li>
<li>
<p>Change 23.3.5.3 <a href="https://wg21.link/deque.capacity">[deque.capacity]</a> as indicated:</p>
<blockquote>
<blockquote>
<pre>
void shrink_to_fit();
</pre>
</blockquote>
<p>
-5- <i>Requires:</i> <code>T</code> shall be <i><code>Cpp17MoveInsertable</code></i>
into <code>*this</code>.
</p><p>
-6- <i>Effects:</i> <code>shrink_­to_­fit</code> is a non-binding request to reduce
memory use but does not change the size of the sequence. [ <i>Note:</i> The
request is non-binding to allow latitude for implementation-specific
optimizations. &mdash;<i>end note</i> ] If <ins>the size is equal to
the old capacity, or if</ins> an exception is thrown other than by
the move constructor of a non-<i><code>Cpp17CopyInsertable</code></i>
<code>T</code><ins>, then</ins> there are no effects.
</p><p>
-7- <i>Complexity:</i> <ins>If the size is not equal to the old capacity,</ins>
linear in the size of the sequence<ins>; otherwise constant</ins>.
</p><p>
-8- <i>Remarks:</i> <del><code>shrink_to_fit</code></del> <ins>If the size is not
equal to the old capacity, then</ins> invalidates all the references, pointers,
and iterators referring to the elements in the sequence<ins>,</ins> as well as
the past-the-end iterator.
</p>
</blockquote>
</li>
<li>
<p>Change 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a> as indicated:</p>
<blockquote>
<blockquote>
<pre>
void reserve(size_type n);
</pre>
</blockquote>
<p>[&hellip;]</p>
<p>
-7- <i>Remarks:</i> Reallocation invalidates all the references, pointers, and
iterators referring to the elements in the sequence<ins>, as well as the
past-the-end iterator</ins>. <ins>[ <i>Note:</i> If no reallocation happens,
they remain valid. &mdash; <i>end note</i> ]</ins> No reallocation shall take place
during insertions that happen after a call to <code>reserve()</code> until <del>the
time when</del> an insertion would make the size of the vector greater than the
value of <code>capacity()</code>.
</p>
<blockquote>
<pre>
void shrink_to_fit();
</pre>
</blockquote>
<p>[&hellip;]</p>
<p>
-10- <i>Complexity:</i> <ins>If reallocation happens,</ins> linear in the size
of the sequence.
</p><p>
-11- <i>Remarks:</i> Reallocation invalidates all the references, pointers, and
iterators referring to the elements in the sequence<ins>,</ins> as well as the
past-the-end iterator. <ins>[ <i>Note:</i></ins> If no reallocation happens,
they remain valid. <ins>&mdash; <i>end
note</i> ]</ins>
</p>
</blockquote>
</li>
<li>
<p>Change 23.3.13.5 <a href="https://wg21.link/vector.modifiers">[vector.modifiers]</a> as indicated:</p>
<blockquote>
<p>
-1- <i>Remarks:</i> Causes reallocation if the new size is greater than the old
capacity. Reallocation invalidates all the references, pointers, and iterators
referring to the elements in the sequence <ins>as well as the past-the-end
iterator</ins>. If no reallocation happens, <del>all the iterators and
references</del> <ins>then references, pointers, and iterators</ins> before the
insertion point remain valid <ins>but those at or after the insertion point,
including the past-the-end iterator, are invalidated</ins>.
If an exception is thrown [&hellip;]
</p><p>
-2- <i>Complexity:</i> <del>The complexity is</del> <ins>If reallocation
happens, linear in the number of elements of the resulting vector;
otherwise</ins> linear in the number of elements inserted plus the distance to
the end of the vector.
</p>
</blockquote>
</li>
</ol>





</body>
</html>
