<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<head>
<style>BODY, P, DIV, H1, H2, H3, H4, H5, H6, ADDRESS, OL, UL, LI, TITLE, TD, OPTION, SELECT 
{ 
 font-family: Verdana 
}
BODY, P, DIV, ADDRESS, OL, UL, LI, TITLE, TD, OPTION, SELECT  
{  
  font-size: 10.0pt; 
  margin-top:0pt;  
  margin-bottom:0pt;  
} 
BODY, P
{
  margin-left:0pt; 
  margin-right:0pt;
}
BODY
{
  background: white;
  margin: 6px;
  padding: 0px;
}
h6 { font-size: 10pt }
h5 { font-size: 11pt }
h4 { font-size: 12pt }
h3 { font-size: 13pt }
h2 { font-size: 14pt }
h1 { font-size: 16pt }
blockquote { padding: 10px; border: 1px #DDDDDD dashed }
a img {	border: 0; }
table.zeroBorder {
	border-width: 1px 1px 1px 1px;
	border-style: dotted dotted dotted dotted;
	border-color: gray gray gray gray;
}
table.zeroBorder th {
	border-width: 1px 1px 1px 1px;
	border-style: dotted dotted dotted dotted;
	border-color: gray gray gray gray;
}
table.zeroBorder td {
	border-width: 1px 1px 1px 1px;
	border-style: dotted dotted dotted dotted;
	border-color: gray gray gray gray;
}
.hiddenStyle {
		visibility: hidden; 
		position: absolute;
		z-Index: 1;
		paddingRight: 0;
		background: white
	}
.misspell { background-image: url('/images/misspell.gif'); background-repeat: repeat-x; background-position: bottom }
@media screen {
.pb { border-top: 1px dashed #C0C0C0; border-bottom: 1px dashed #C0C0C0 }
.writely-comment { font-size: 9pt; line-height: 1.4em; padding: 1px; border: 1px dashed #C0C0C0 }
}
@media print {
.pb { border-top: 0px; border-bottom: 0px }
.writely-comment { display: none }
}
@media screen,print {
.pb { height: 1px }
}
</style></head>
<body revision='ddd5crnh_22hsf99j:167'>
Matthew Austern &lt;austern@google.com&gt;<br>
N2256=07-0116<br>
2007-04-18<br>
<br>
<h1>
  Container insert/erase and iterator constness
</h1>
Ten years ago, just before the standard was finished, Dave Abrahams pointed out
that the container requirements were too fussy about constness. Table 82,
sequence requirements, says that the expression for single-element
<span style="FONT-FAMILY:Courier New">sequence insert</span> is
<span style="FONT-FAMILY:Courier New">a.insert(p, t)</span>, where
<span style="FONT-FAMILY:Courier New">p</span> stands for "a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>". The requirement tables say
similar things for sequence <span style="FONT-FAMILY:Courier New">erase</span>,
and for associative container <span style="FONT-FAMILY:Courier New">erase</span>
and <span style="FONT-FAMILY:Courier New">insert</span>. This is too strict,
because these requirements confuse iterator constness and container constness.
The container is being modified, but the iterator, which is used only for
positioning, is not. There is no reason to forbid it from being a const
iterator.<br>
<br>
Making the iterator argument
<span style="FONT-FAMILY:Courier New">const_iterator</span> does raise another
question. Currently the return type for the single-element sequence
<span style="FONT-FAMILY:Courier New">insert</span>, both versions of sequence
<span style="FONT-FAMILY:Courier New">erase</span>, single-element associative
container <span style="FONT-FAMILY:Courier New">insert</span>, and both versions
of associative container <span style="FONT-FAMILY:Courier New">erase</span>, is
<span style="FONT-FAMILY:Courier New">iterator</span>. If we change the
arguments without making any other changes, then we will have functions with a
<span style="FONT-FAMILY:Courier New">const_iterator</span> argument type and an
<span style="FONT-FAMILY:Courier New">iterator</span> return type. Strictly
speaking, this is not a violation of const correctness. It doesn't turn a
<span style="FONT-FAMILY:Courier New">const_iterator</span> into an
<span style="FONT-FAMILY:Courier New">iterator</span>; all it does is generate
an <span style="FONT-FAMILY:Courier New">iterator</span> given a non-const
container, and of course there is nothing extraordinary about that. Still, this
member function made some committee members uncomfortable enough to look for an
alternative fix: overloading these member functions on
<span style="FONT-FAMILY:Courier New">iterator</span> and
<span style="FONT-FAMILY:Courier New">const_iterator</span>, so that the return
type matches the argument type.<br>
<br>
This problem was never fixed for the sequence containers
(<span style="FONT-FAMILY:Courier New">vector</span>,
<span style="FONT-FAMILY:Courier New">list</span>, and
<span style="FONT-FAMILY:Courier New">deque</span>) or for the associative
containers (<span style="FONT-FAMILY:Courier New">map</span>,
<span style="FONT-FAMILY:Courier New">set</span>,
<span style="FONT-FAMILY:Courier New">multimap</span>, and
<span style="FONT-FAMILY:Courier New">multiset</span>). It was fixed for the
unordered associative containers
(<span style="FONT-FAMILY:Courier New">unordered_map</span>,
<span style="FONT-FAMILY:Courier New">unordered_set</span>,
<span style="FONT-FAMILY:Courier New">unordered_multimap</span>, and
<span style="FONT-FAMILY:Courier New">unordered_multiset</span>). Based on the
results of an LWG straw poll, the unordered associative containers use the
second alternative:&nbsp; two overloaded member functions.<br>
<br>
We ought to fix this problem for the sequences containers and the associative
containers. It would be silly to release two standards with this known defect,
or to treat this issue differently in the unordered associative containers than
in the sequences and the associative containers.<br>
<br>
We have two options for this fix: either apply the same fix to sequences and
associative containers as we already did for unordered associative containers,
or consistently change all of the containers to use a single member function
with a <span style="FONT-FAMILY:Courier New">const_iterator</span> argument and
an <span style="FONT-FAMILY:Courier New">iterator</span> return type. I present
wording for both options.<br>
<br>
I prefer option B, because it's simpler: I believe that these overloads are
cumbersome and add no const correctness value. I am providing wording for both
options because option A is more consistent with the straw poll from the 2004
Redmond meeting.<br>
<h2>
  Option A
</h2>
In 2.3.1.1 [lib.sequence.reqmts] paragraph 3, replace
"<span style="FONT-FAMILY:Courier New">p</span> denotes a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> denotes a valid dereferenceable
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> denotes a valid range in
<span style="FONT-FAMILY:Courier New">a</span>" with
"<span style="FONT-FAMILY:Courier New">p</span> denotes a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">pc</span> denotes a valid const iterator
to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> denotes a valid dereferenceable
iterator to <span style="FONT-FAMILY:Courier New">a</span>,&nbsp;
<span style="FONT-FAMILY:Courier New">qc</span> denotes a valid dereferenceable
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> denotes a valid range in
<span style="FONT-FAMILY:Courier New">a,
</span><span style="FONT-FAMILY:Courier New">[qc1, qc2)</span> denotes a valid
range of const iterators in <span style="FONT-FAMILY:Courier New">a</span>".<br>
<br>
In Table 82 (sequence requirements):<br>
<ul>
  <li>
    Add another row after <span style="FONT-FAMILY:Courier New">a.insert(p,
    t)</span>: expression <span style="FONT-FAMILY:Courier New">a.insert(pc,
    t)</span>, return type
    <span style="FONT-FAMILY:Courier New">const_iterator</span>, and description
    "inserts a copy of <span style="FONT-FAMILY:Courier New">t</span> before
    <span style="FONT-FAMILY:Courier New">pc</span>".
  </li>
  <li>
    Change <span style="FONT-FAMILY:Courier New">a.insert(p, n, t)</span> to
    <span style="FONT-FAMILY:Courier New">a.insert(pc, n,
    t)<span style=FONT-FAMILY:Verdana>, and make the corresponding change in the
    description.</span><br>
    </span>
  </li>
  <li>
    Change <span style="FONT-FAMILY:Courier New">a.insert(p, i, j)</span> to
    <span style="FONT-FAMILY:Courier New">a.insert(pc, i,
    j)</span><span style="FONT-FAMILY:Courier New"><span style=FONT-FAMILY:Verdana>,
    and make the corresponding change in the description.</span></span>
  </li>
  <li>
    Add another row after
    <span style="FONT-FAMILY:Courier New">a.erase(q)</span>: expression
    <span style="FONT-FAMILY:Courier New">a.erase(qc)</span>, return type
    <span style="FONT-FAMILY:Courier New">const_iterator</span>, and description
    "erases the element pointed to by
    <span style="FONT-FAMILY:Courier New">qc</span>".
  </li>
  <li>
    Add another row after <span style="FONT-FAMILY:Courier New">a.erase(q1,
    q2)</span>: expression <span style="FONT-FAMILY:Courier New">a.erase(qc1,
    qc2)</span>, return type
    <span style="FONT-FAMILY:Courier New">const_iterator</span> and description
    "erases the elements in the range
    <span style="FONT-FAMILY:Courier New">[qc1, qc2)</span>".
  </li>
</ul>
<br>
In 23.1.2 [lib.associative.reqmts] paragraph 7, replace
"<span style="FONT-FAMILY:Courier New">p</span> is a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> is a valid dereferenceable
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> is a valid range in
<span style="FONT-FAMILY:Courier New">a</span>" with
"<span style="FONT-FAMILY:Courier New">p</span> is a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">pc</span> is a valid const iterator to
<span style="FONT-FAMILY:Courier New">a<span style=FONT-FAMILY:Verdana>,
</span></span><span style="FONT-FAMILY:Courier New">q</span> is a valid
dereferenceable iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">qc</span> is a valid dereferenceable const
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> is a valid range in
<span style="FONT-FAMILY:Courier New">a<span style=FONT-FAMILY:Verdana>,&nbsp;</span></span><span style="FONT-FAMILY:Courier New">[qc1,
q2)</span> is a valid range of const iterators in
<span style="FONT-FAMILY:Courier New">a</span><span style="FONT-FAMILY:Courier New">.</span>"<br>
<br>
In table 84 (associative container requirements):<br>
<ul>
  <li>
    Add another row after <span style="FONT-FAMILY:Courier New">a.insert(p,
    t)</span>: expression <span style="FONT-FAMILY:Courier New">a.insert(pc,
    t)</span>, return type
    <span style="FONT-FAMILY:Courier New">const_iterator</span>, description and
    complexity "same as above".
  </li>
  <li>
    Add another row following
    <span style="FONT-FAMILY:Courier New">a.erase(q)</span>: expression
    <span style="FONT-FAMILY:Courier New">a.erase(qc)</span>, return type
    <span style="FONT-FAMILY:Courier New">const_iterator</span>, description and
    complexity "same as above".
  </li>
  <li>
    Add another row following <span style="FONT-FAMILY:Courier New">a.erase(q1,
    q2)</span>: expression <span style="FONT-FAMILY:Courier New">a.erase(qc1,
    qc2)</span>, return type
    <span style="FONT-FAMILY:Courier New">const_iterator</span>, and description
    and complexity "same as above".
  </li>
</ul>
<br>
In the class synopses of 23.2.1 [lib.deque], 23.2.2 [lib.list], 23.2.4
[lib.vector], and 23.2.5 [lib.vector.bool], and in the member function
descriptions in 23.2.1.3 [lib.deque.modifiers], 23.2.2.3 [lib.list.modifiers],
and 23.2.4.3 [lib.vector.modifiers], add the new signatures<br>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New">const_iterator insert(const_iterator
  position, const T&amp; x);</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">const_iterator erase(const_iterator
  position);</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">const_iterator erase(const_iterator
  first, const_iterator last);</span><br>
</div>
and change the signatures of the other two overloads of insert to<br>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New">void insert(const_iterator position,
  size_type n, const T&amp; x);</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">template &lt;class
  InputIterator&gt;</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">&nbsp; void insert(const_iterator
  position, InputIterator first, InputIterator last);</span><br>
</div>
<br>
In the class synopses in 23.3.1 [lib.map], 23.3.2 [lib.multimap], 23.3.3
[lib.set], and 23.3.4 [lib.multiset], change the
signatures<span style="FONT-FAMILY:Courier New"></span><br style="FONT-FAMILY:Courier New">
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New">iterator insert(iterator position, const
  value_type&amp; x);
  </span><span style="FONT-FAMILY:Courier New"></span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">iterator erase(iterator position);
  </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">iterator erase(iterator first, iterator
  last);</span><br>
</div>
to<span style="FONT-FAMILY:Courier New"></span><br style="FONT-FAMILY:Courier New">
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New"> iterator insert(iterator position,
  const value_type&amp; x);<br>
  </span><span style="FONT-FAMILY:Courier New">const_iterator
  insert(const_iterator position, const value_type&amp; x);
  </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New"></span><span style="FONT-FAMILY:Courier New">iterator
  erase(iterator position);<br>
  </span><span style="FONT-FAMILY:Courier New"></span><span style="FONT-FAMILY:Courier New">const_iterator
  erase(const_iterator position);&nbsp;
  </span><span style="FONT-FAMILY:Courier New"></span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New"> iterator erase(iterator first, iterator
  last);<br>
  </span><span style="FONT-FAMILY:Courier New">const_iterator
  erase(const_iterator first, iterator last);</span><br>
</div>
<h2>
  Option B
</h2>
In 2.3.1.1 [lib.sequence.reqmts] paragraph 3, replace
"<span style="FONT-FAMILY:Courier New">p</span> denotes a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> denotes a valid dereferenceable
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> denotes a valid range in
<span style="FONT-FAMILY:Courier New">a</span>" with
"<span style="FONT-FAMILY:Courier New">p</span> denotes a valid const iterator
to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> denotes a valid dereferenceable
const iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> denotes a valid range of
const iterators in <span style="FONT-FAMILY:Courier New">a</span>"<br>
<br>
In 23.1.2 [lib.associative.reqmts] paragraph 7, replace
"<span style="FONT-FAMILY:Courier New">p</span> is a valid iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> is a valid dereferenceable
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> is a valid range in
<span style="FONT-FAMILY:Courier New">a</span>" with
"<span style="FONT-FAMILY:Courier New">p</span> is a valid const iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> is a valid dereferenceable const
iterator to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> is a valid range of const
iterators in <span style="FONT-FAMILY:Courier New">a</span>".<br>
<br>
In the class synopses of 23.2.1 [lib.deque], 23.2.2 [lib.list], and 23.2.4
[lib.vector],<br>
and in the member function descriptions in 23.2.1.3 [lib.deque.modifiers],
23.2.2.3 [lib.list.modifiers], and 23.2.4.3 [lib.vector.modifiers], change the
signatures of insert and erase to<br>
<div style="MARGIN-LEFT:40px; FONT-FAMILY:Courier New">
  iterator insert(const_iterator position, const T&amp; x);<br>
</div>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New">void insert(const_iterator position,
  size_type n, const T&amp; x);</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">template &lt;class
  InputIterator&gt;</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">&nbsp; void insert(const_iterator
  position, InputIterator first, InputIterator last);<br>
  iterator erase(const_iterator
  position);</span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New"> iterator erase(const_iterator first,
  const_iterator last);</span><br>
</div>
<br>
In the class synopses in 23.3.1 [lib.map], 23.3.2 [lib.multimap], 23.3.3
[lib.set], and 23.3.4 [lib.multiset], change the signatures<br>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New"> iterator insert(iterator position,
  const value_type&amp; x); </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New"> iterator erase(iterator position);
  </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New"> iterator erase(iterator first, iterator
  last);</span><br>
</div>
to<br>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New"> iterator insert(const_iterator
  position, const value_type&amp; x);
  </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New"> iterator erase(const_iterator
  position); </span><span style="FONT-FAMILY:Courier New"><br>
  iterator erase(const_iterator first, iterator last);</span><br>
</div>
<br>
In 23.1.3 [lib.unord.req] paragraph 9, change
"<span style="FONT-FAMILY:Courier New">p</span> and
<span style="FONT-FAMILY:Courier New">q2</span> are valid iterators to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> and
<span style="FONT-FAMILY:Courier New">q1</span> are valid dereferenceable
iterators to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> is a valid range in
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">r</span> and
<span style="FONT-FAMILY:Courier New">r1</span> are valid dereferenceable const
iterators to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">r2</span> is a valid const iterator to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[r1, r2)</span> is a valid range in
<span style="FONT-FAMILY:Courier New">a</span>" to
"<span style="FONT-FAMILY:Courier New">p</span> and
<span style="FONT-FAMILY:Courier New">q2</span> are valid const iterators to
<span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">q</span> and
<span style="FONT-FAMILY:Courier New">q1</span> are valid dereferenceable const
iterators to <span style="FONT-FAMILY:Courier New">a</span>,
<span style="FONT-FAMILY:Courier New">[q1, q2)</span> is a valid range in
<span style="FONT-FAMILY:Courier New">a</span><span style="FONT-FAMILY:Courier New"></span>".<br>
<br>
In table 86 (unordered associative container requirements), delete the rows for
<span style="FONT-FAMILY:Courier New">a.insert(r, t)</span>,
<span style="FONT-FAMILY:Courier New">a.erase(r)</span>, and
<span style="FONT-FAMILY:Courier New">a.erase(r1, r2)</span>.<br>
<br>
In the class synopses in 23.4.1 [lib.unord.map], 23.4.2 [lib.unord.multimap],
23.4.3 [lib.unord.set], and 23.4.4 [lib.unord.multiset], replace the signatures<br>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New">iterator insert(iterator hint, const
  value_type&amp; obj); </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">const_iterator insert(const_iterator
  hint, const value_type&amp; obj); </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">iterator erase(iterator position);
  </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">const_iterator erase(const_iterator
  position); </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">iterator erase(iterator first, iterator
  last); </span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">const_iterator erase(const_iterator
  first, const_iterator last); </span><br>
</div>
with<br>
<div style=MARGIN-LEFT:40px>
  <span style="FONT-FAMILY:Courier New">iterator insert(const_iterator hint,
  const value_type&amp; obj);
  </span><span style="FONT-FAMILY:Courier New"></span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">iterator erase(const_iterator position);
  </span><span style="FONT-FAMILY:Courier New"></span><br style="FONT-FAMILY:Courier New">
  <span style="FONT-FAMILY:Courier New">iterator erase(const_iterator first,
  iterator last); </span><br style="FONT-FAMILY:Courier New">
</div>
<span style="FONT-FAMILY:Courier New"></span><br></body>
</html>