<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 299: Incorrect return types for iterator dereference</title>
<meta property="og:title" content="Issue 299: Incorrect return types for iterator dereference">
<meta property="og:description" content="C++ library issue. Status: NAD Editorial">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue299.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_Editorial">NAD Editorial</a> status.</em></p>
<h3 id="299"><a href="lwg-closed.html#299">299</a>. Incorrect return types for iterator dereference</h3>
<p><b>Section:</b> 24.3.5.6 <a href="https://wg21.link/bidirectional.iterators">[bidirectional.iterators]</a>, 24.3.5.7 <a href="https://wg21.link/random.access.iterators">[random.access.iterators]</a> <b>Status:</b> <a href="lwg-active.html#NAD_Editorial">NAD Editorial</a>
 <b>Submitter:</b> John Potter <b>Opened:</b> 2001-01-22 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#bidirectional.iterators">issues</a> in [bidirectional.iterators].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD Editorial">NAD Editorial</a> status.</p>
<p><b>Discussion:</b></p>
<p>
In section 24.3.5.6 <a href="https://wg21.link/bidirectional.iterators">[bidirectional.iterators]</a>,
Table 75 gives the return type of <code>*r--</code> as convertible to <code>T</code>.  This is
not consistent with Table 74 which gives the return type of <code>*r++</code> as
<code>T&amp;</code>.  <code>*r++ = t</code> is valid while <code>*r-- = t</code> is invalid.
</p>

<p>
In section 24.3.5.7 <a href="https://wg21.link/random.access.iterators">[random.access.iterators]</a>,
Table 76 gives the return type of <code>a[n]</code> as convertible to <code>T</code>.  This is
not consistent with the semantics of <code>*(a + n)</code> which returns <code>T&amp;</code> by
Table 74.  <code>*(a + n) = t</code> is valid while <code>a[n] = t</code> is invalid.
</p>

<p>
Discussion from the Copenhagen meeting: the first part is
uncontroversial.  The second part, <code>operator[]</code> for Random Access
Iterators, requires more thought.  There are reasonable arguments on
both sides.  Return by value from <code>operator[]</code> enables some potentially
useful iterators, e.g. a random access "iota iterator" (a.k.a
"counting iterator" or "int iterator").  There isn't any obvious way
to do this with return-by-reference, since the reference would be to a
temporary.  On the other hand, <code>reverse_iterator</code> takes an
arbitrary Random Access Iterator as template argument, and its
<code>operator[]</code> returns by reference.  If we decided that the return type
in Table 76 was correct, we would have to change
<code>reverse_iterator</code>.  This change would probably affect user
code.
</p>

<p>
History: the contradiction between <code>reverse_iterator</code> and the
Random Access Iterator requirements has been present from an early
stage.  In both the STL proposal adopted by the committee
(N0527==94-0140) and the STL technical report (HPL-95-11 (R.1), by
Stepanov and Lee), the Random Access Iterator requirements say that
<code>operator[]</code>'s return value is "convertible to <code>T</code>".  In N0527
reverse_iterator's <code>operator[]</code> returns by value, but in HPL-95-11
(R.1), and in the STL implementation that HP released to the public,
reverse_iterator's <code>operator[]</code> returns by reference.  In 1995, the
standard was amended to reflect the contents of HPL-95-11 (R.1).  The
original intent for <code>operator[]</code> is unclear.
</p>

<p>
In the long term it may be desirable to add more fine-grained 
iterator requirements, so that access method and traversal strategy
can be decoupled.  (See "Improved Iterator Categories and
Requirements", N1297 = 01-0011, by Jeremy Siek.)  Any decisions
about issue 299 should keep this possibility in mind.
</p>

<p>Further discussion: I propose a compromise between John Potter's
resolution, which requires <code>T&amp;</code> as the return type of
<code>a[n]</code>, and the current wording, which requires convertible to
<code>T</code>. The compromise is to keep the convertible to <code>T</code>
for the return type of the expression <code>a[n]</code>, but to also add
<code>a[n] = t</code> as a valid expression. This compromise "saves" the
common case uses of random access iterators, while at the same time
allowing iterators such as counting iterator and caching file
iterators to remain random access iterators (iterators where the
lifetime of the object returned by <code>operator*()</code> is tied to the
lifetime of the iterator).
</p>

<p>
Note that the compromise resolution necessitates a change to
<code>reverse_iterator</code>. It would need to use a proxy to support
<code>a[n] = t</code>.
</p>

<p>
Note also there is one kind of mutable random access iterator that
will no longer meet the new requirements. Currently, iterators that
return an r-value from <code>operator[]</code> meet the requirements for a
mutable random access iterator, even though the expression <code>a[n] =
t</code> will only modify a temporary that goes away. With this proposed
resolution, <code>a[n] = t</code> will be required to have the same
operational semantics as <code>*(a + n) = t</code>.
</p>

<p><i>[
2009-07-28 Reopened by Alisdair.  No longer solved by concepts.
]</i></p>


<p><i>[
2009-09-18 Alisdair adds:
]</i></p>


<blockquote>
<p>
Why can't we write through the reference returned from <code>operator[]</code> on a
random access iterator?
</p>

<p>
Recommended solution:
</p>

<p>
In table Table 104 &mdash; Random access iterator requirements, replace
</p>

<blockquote><p>
<code>a[n]</code> : convertible to <del><code>const T &amp;</code></del>
<ins><code>T&amp;</code> if <code>X</code> is mutable, otherwise convertible to <code>const T&amp;</code></ins>
</p></blockquote>
</blockquote>

<p><i>[
2009-10 Santa Cruz:
]</i></p>


<blockquote><p>
Leave Open. Alisdair to spearhead a paper on revivification.
</p></blockquote>

<p><i>[
2010 Pittsburgh:  Moved to NAD Editorial.  Rationale added below.
]</i></p>




<p><b>Rationale:</b></p>
<p>
Solved by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3066.html">N3066</a>.
</p>


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

<p>
In section 24.1.4 [lib.bidirectdional.iterators], change the return
type in table 75 from &quot;convertible to <code>T</code>&quot; to
<code>T&amp;</code>.
</p>

<p>
In section 24.1.5 [lib.random.access.iterators], change the
operational semantics for <code>a[n]</code> to &quot; the r-value of
<code>a[n]</code> is equivalent to the r-value of <code>*(a +
n)</code>&quot;. Add a new row in the table for the expression <code>a[n] = t</code>
with a return type of convertible to <code>T</code> and operational semantics of
<code>*(a + n) = t</code>.
</p>

<p><i>[Lillehammer: Real problem, but should be addressed as part of
  iterator redesign]</i></p>




<p><b>Rationale:</b></p>
<p><i>[
San Francisco:
]</i></p>


<blockquote><p>
Solved by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2758.pdf">N2758</a>.
</p></blockquote>







</body>
</html>
