<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2356: Stability of erasure in unordered associative containers</title>
<meta property="og:title" content="Issue 2356: Stability of erasure in unordered associative containers">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2356.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++14">C++14</a> status.</em></p>
<h3 id="2356"><a href="lwg-defects.html#2356">2356</a>. Stability of erasure in unordered associative containers</h3>
<p><b>Section:</b> 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz <b>Opened:</b> 2014-01-21 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="lwg-index-open.html#unord.req">active issues</a> in [unord.req].</p>
<p><b>View all other</b> <a href="lwg-index.html#unord.req">issues</a> in [unord.req].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++14">C++14</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Issue <a href="lwg-defects.html#518" title="Are insert and erase stable for unordered_multiset and unordered_multimap? (Status: CD1)">518</a><sup><a href="https://cplusplus.github.io/LWG/issue518" title="Latest snapshot">(i)</a></sup> resolution for unordered associative containers, modelled after that of issue <a href="lwg-defects.html#371" title="Stability of multiset and multimap member functions (Status: CD1)">371</a><sup><a href="https://cplusplus.github.io/LWG/issue371" title="Latest snapshot">(i)</a></sup>, 
which is related to associative containers, states that insertion, erasure and rehashing preserve the relative ordering 
of equivalent elements. Unfortunately, this is not sufficient to guarantee the validity of code such as this:
</p>
<blockquote><pre>
std::unordered_multimap&lt;int, int&gt; m;
auto i = m.begin();
while (i != m.end()) {
  if (pred(i))
    m.erase(i++);
  else
    ++i;
}
</pre></blockquote>
<p>
(which is a direct translation from <code>multimap</code> to <code>unordered_multimap</code> of the motivating example in <a href="lwg-defects.html#371" title="Stability of multiset and multimap member functions (Status: CD1)">371</a><sup><a href="https://cplusplus.github.io/LWG/issue371" title="Latest snapshot">(i)</a></sup>), 
or even this:
</p>
<blockquote><pre>
std::unordered_multimap&lt;int, int&gt; m;
auto p = m.equal_range(k);
while (p.first != p.second) {
  if (pred(p.first))
    m.erase((p.first)++);
  else
    ++(p.first);
}
</pre></blockquote>
<p>
because the relative ordering of <em>non-equivalent</em> elements elements could potentially change after erasure (not that any actual 
implementation does that, anyway). Such an underspecification does not happen for regular associative containers, where the 
relative ordering of non-equivalent elements is kept by design.
</p>

<p><i>[2014-02-13 Issaquah: Move to Immediate]</i></p>




<p id="res-2356"><b>Proposed resolution:</b></p>
<p>This wording is relative to N3797.</p>

<ol>
<li><p>Modify 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>, p14 as indicated:</p>

<blockquote><p>
-14- The <code>insert</code> and <code>emplace</code> members shall not affect the validity of references to container elements, but may
invalidate all iterators to the container. The <code>erase</code> members shall invalidate only iterators and references
to the erased elements<ins>, and preserve the relative order of the elements that are not erased</ins>.
</p></blockquote>
</li>
</ol>





</body>
</html>
