<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 579: erase(iterator) for unordered containers should not return an iterator</title>
<meta property="og:title" content="Issue 579: erase(iterator) for unordered containers should not return an iterator">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue579.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#NAD">NAD</a> status.</em></p>
<h3 id="579"><a href="lwg-closed.html#579">579</a>. <code>erase(iterator)</code> for unordered containers should not return an iterator</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#NAD">NAD</a>
 <b>Submitter:</b> Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz <b>Opened:</b> 2006-06-13 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</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#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p><b>Addresses ES-2</b></p>

<p>
See
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2023.pdf">N2023</a>
for full discussion.
</p>

<p><i>[
2009-12-11 Paolo opens:
]</i></p>


<blockquote><p>
I'm asking for DR 579 to be re-opened, basing on recent discussions on the
library reflector, see Message c++std-lib-26040 and replies.
</p></blockquote>

<p><i>[
2010-02-07 Paolo updates wording.
]</i></p>


<blockquote><p>
As pointed out by Chris in c++std-lib-26040, that an
<code>erase(unordered_container, iterator)</code> returning an <code>iterator</code> can
easily implemented in user code, if needed; that actually returning an
<code>iterator</code> costs nothing for the overload taking two <code>iterator</code>s,
thus that proposed change is only for consistency; that
<code>forward_list::erase_after</code> also returns <code>void</code> (for different
reasons, granted, but isn't that any "<code>erase</code>" function in the containers
uniformly returns an <code>iterator</code>); that, also in thread started by Chris'
message, Alberto pointed out that the proxy idea isn't a good one; that users
both of the GNU and Boost implementations are reporting serious performance
problems with the current version returning an <code>iterator</code>.
</p></blockquote>

<p><i>[
2010-02-07 Original wording saved here:
]</i></p>


<blockquote class="note">
<p>
Option 1:
</p>

<p>
The problem can be eliminated by omitting the requirement that <code>a.erase(q)</code> return an 
iterator. This is, however, in contrast with the equivalent requirements for other 
standard containers.
</p>

<p>
Option 2:
</p>

<p>
<code>a.erase(q)</code> can be made to compute the next iterator only when explicitly requested: 
the technique consists in returning a proxy object implicitly convertible to <code>iterator</code>, so 
that
</p>

<blockquote><pre>
iterator q1=a.erase(q);
</pre></blockquote>

<p>
works as expected, while
</p>

<blockquote><pre>
a.erase(q);
</pre></blockquote>

<p>
does not ever invoke the conversion-to-iterator operator, thus avoiding the associated 
computation. To allow this technique, some sections of TR1 along the line "return value 
is an iterator..." should be changed to "return value is an unspecified object implicitly 
convertible to an iterator..." Although this trick is expected to work transparently, it can 
have some collateral effects when the expression <code>a.erase(q)</code> is used inside generic 
code.
</p>

</blockquote>

<p><i>[
2010-03-27 Joaqu&iacute;n adds:
]</i></p>


<blockquote>
<p>
Signature of <code>iterator erase(const_iterator)</code> should be changed to <code>void
erase(const_iterator)</code>. If this is not viable an acceptable tradeoff
could be to make the return type of <code>erase(const_iterator)</code>
<i>implementation defined</i>.
</p>

<p>
The standard should allow implementations of unordered associative
containers using either singly or doubly linked lists.
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2023.pdf">N2023</a>
proves that singly-linked lists implementations cannot provide the required
complexity for <code>iterator erase(const_iterator)</code>. Thus, some action is
needed to allow both implementations.
</p>

<p> 
Option 1: Changing the required complexity from O(1) to O(log n). This option
merely masks a design flaw. Users are forcefully penalized for what they don't
use (the returned iterator). Besides, they would have to learn about the
pathological (yet very real) situations where using <code>erase</code> can lead to
quadratic performance. Two out of these three objections remain even if some
alternative member function like <code>void quick_erase(const_iterator)</code> is
thrown in to the interface.
</p>

<p> 
Some objections have been expressed to changing return type of <code>erase</code> to
<code>void</code>, arguing that it would break current existing practice with
standard library implementations based on doubly-linked lists, where the problem
does not occur. However implementations based on drafts should not block the
resolution of a serious design issue, more so when the issue will hurt future
users of C++, as it's happening already.
</p>

<p> 
Option 2: Make <code>erase</code> return type <i>implementation defined</i>. There's
a possible tradeoff with the objectors above consisting in changing the
signature to <i>implementation defined</i> <code>erase(iterator)</code>, so that
returning an iterator is indeed a valid extension. To this it can be argued that
this would make implementantions returning an iterator look as somehow promoting
proprietary extensions: this in my opinion is not a valid argument since those
implementations are <em>already</em> extending the required interface by
providing bidirectional iterators (just forward iterators are required).
</p>
</blockquote>

<p><i>[
2010 Rapperswil:
]</i></p>


<blockquote>
<p>
The issue was lengthy discussed and implementation experience was demonstrated that a non-void return
type is implementable for both single-linked and double-linked lists without loss of efficiency.
</p>

<p>
By a 12-1-1-0 poll voted to keep the return type of erase as <code>iterator</code> instead of 
<code>void</code> and a second 0-0-3-10 poll rejected the additional proposal to add a 
<code>quick_erase</code> returning <code>void</code>, thus LWG decided for NAD.
</p>
</blockquote>


<p><b>Rationale:</b></p>

<p>
No consensus for a change.
</p>



<p id="res-579"><b>Proposed resolution:</b></p>





</body>
</html>
