<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 179: Comparison of const_iterators to iterators doesn't work</title>
<meta property="og:title" content="Issue 179: Comparison of const_iterators to iterators doesn't work">
<meta property="og:description" content="C++ library issue. Status: CD1">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue179.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#CD1">CD1</a> status.</em></p>
<h3 id="179"><a href="lwg-defects.html#179">179</a>. Comparison of const_iterators to iterators doesn't work</h3>
<p><b>Section:</b> 23.2 <a href="https://wg21.link/container.requirements">[container.requirements]</a> <b>Status:</b> <a href="lwg-active.html#CD1">CD1</a>
 <b>Submitter:</b> Judy Ward <b>Opened:</b> 1998-07-02 <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#container.requirements">issues</a> in [container.requirements].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#CD1">CD1</a> status.</p>
<p><b>Discussion:</b></p>
<p>Currently the following will not compile on two well-known standard
library implementations:</p>

<blockquote>
  <pre>#include &lt;set&gt;
using namespace std;

void f(const set&lt;int&gt; &amp;s)
{
  set&lt;int&gt;::iterator i;
  if (i==s.end()); // s.end() returns a const_iterator
}</pre>
</blockquote>

<p>
The reason this doesn't compile is because operator== was implemented
as a member function of the nested classes set:iterator and
set::const_iterator, and there is no conversion from const_iterator to
iterator. Surprisingly, (s.end() == i) does work, though, because of
the conversion from iterator to const_iterator.
</p>

<p>
I don't see a requirement anywhere in the standard that this must
work. Should there be one?  If so, I think the requirement would need
to be added to the tables in section 24.1.1. I'm not sure about the
wording.  If this requirement existed in the standard, I would think
that implementors would have to make the comparison operators
non-member functions.</p>

<p>This issues was also raised on comp.std.c++ by Darin
Adler.&nbsp; The example given was:</p>

<blockquote>
  <pre>bool check_equal(std::deque&lt;int&gt;::iterator i,
std::deque&lt;int&gt;::const_iterator ci)
{
return i == ci;
}</pre>
</blockquote>

<p>Comment from John Potter:</p>
<blockquote>
    <p>
    In case nobody has noticed, accepting it will break reverse_iterator.
    </p>

    <p>
    The fix is to make the comparison operators templated on two types.
    </p>

    <pre>
    template &lt;class Iterator1, class Iterator2&gt;
    bool operator== (reverse_iterator&lt;Iterator1&gt; const&amp; x,
                     reverse_iterator&lt;Iterator2&gt; const&amp; y);
    </pre>

    <p>
    Obviously:  return x.base() == y.base();
    </p>

    <p>
    Currently, no reverse_iterator to const_reverse_iterator compares are
    valid.
    </p>

    <p>
    BTW, I think the issue is in support of bad code.  Compares should be
    between two iterators of the same type.  All std::algorithms require
    the begin and end iterators to be of the same type. 
    </p>
</blockquote>


<p id="res-179"><b>Proposed resolution:</b></p>
<p>Insert this paragraph after 23.2 <a href="https://wg21.link/container.requirements">[container.requirements]</a> paragraph 7:</p>
<blockquote>
  <p>In the expressions</p>
  <pre>
    i == j
    i != j
    i &lt; j
    i &lt;= j
    i &gt;= j
    i &gt; j
    i - j
  </pre>
  <p>Where i and j denote objects of a container's iterator type,
  either or both may be replaced by an object of the container's
  const_iterator type referring to the same element with no
  change in semantics.</p>
</blockquote>

<p><i>[post-Toronto: Judy supplied a proposed resolution saying that
<code>iterator</code> and <code>const_iterator</code> could be freely mixed in
iterator comparison and difference operations.]</i></p>


<p><i>[Redmond: Dave and Howard supplied a new proposed resolution which
explicitly listed expressions; there was concern that the previous
proposed resolution was too informal.]</i></p>



<p><b>Rationale:</b></p>
<p>
The LWG believes it is clear that the above wording applies only to
the nested types <code>X::iterator</code> and <code>X::const_iterator</code>,
where <code>X</code> is a container.  There is no requirement that
<code>X::reverse_iterator</code> and <code>X::const_reverse_iterator</code>
can be mixed.  If mixing them is considered important, that's a
separate issue.  (Issue <a href="lwg-defects.html#280" title="Comparison of reverse_iterator to const reverse_iterator (Status: CD1)">280</a><sup><a href="https://cplusplus.github.io/LWG/issue280" title="Latest snapshot">(i)</a></sup>.)
</p>




</body>
</html>
