<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 659: istreambuf_iterator should have an operator-&gt;()</title>
<meta property="og:title" content="Issue 659: istreambuf_iterator should have an operator-&gt;()">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue659.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++11">C++11</a> status.</em></p>
<h3 id="659"><a href="lwg-defects.html#659">659</a>. <code>istreambuf_iterator</code> should have an <code>operator-&gt;()</code></h3>
<p><b>Section:</b> 24.6.4 <a href="https://wg21.link/istreambuf.iterator">[istreambuf.iterator]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Niels Dekker <b>Opened:</b> 2007-03-25 <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#istreambuf.iterator">active issues</a> in [istreambuf.iterator].</p>
<p><b>View all other</b> <a href="lwg-index.html#istreambuf.iterator">issues</a> in [istreambuf.iterator].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Greg Herlihy has clearly demonstrated that a user defined input
iterator should have an <code>operator-&gt;()</code>, even if its
value type is a built-in type (comp.std.c++, "Re: Should any iterator
have an <code>operator-&gt;()</code> in C++0x?", March 2007).  And as Howard
Hinnant remarked in the same thread that the input iterator
<code>istreambuf_iterator</code> doesn't have one, this must be a
defect!
</p>
<p>
Based on Greg's example, the following code demonstrates the issue:
</p><pre>
 #include &lt;iostream&gt; 
 #include &lt;fstream&gt;
 #include &lt;streambuf&gt; 

 typedef char C;
 int main ()
 {
   std::ifstream s("filename", std::ios::in);
   std::istreambuf_iterator&lt;char&gt; i(s);

   (*i).~C();  // This is well-formed...
   i-&gt;~C();  // ... so this should be supported!
 }
</pre>
<p>
Of course, <code>operator-&gt;</code> is also needed when the <code>value_type</code> of
<code>istreambuf_iterator</code> is a class.
</p>
<p>
The <code>operator-&gt;</code> could be implemented in various ways.  For instance,
by storing the current value inside the iterator, and returning its
address.  Or by returning a proxy, like <code>operator_arrow_proxy</code>, from
<a href="http://www.boost.org/boost/iterator/iterator_facade.hpp">http://www.boost.org/boost/iterator/iterator_facade.hpp</a>
</p>
<p>
I hope that the resolution of this issue will contribute to getting a
clear and consistent definition of iterator concepts.
</p>

<p><i>[
Kona (2007): The proposed resolution is inconsistent because the return
type of <code>istreambuf_iterator::operator-&gt;()</code> is specified to be <code>pointer</code>,
but the proposed text also states that "<code>operator-&gt;</code> may return a proxy."
]</i></p>


<p><i>[
Niels Dekker (mailed to Howard Hinnant):
]</i></p>

<blockquote>
<p>
The proposed resolution does
not seem inconsistent to me. <code>istreambuf_iterator::operator-&gt;()</code> should
have <code>istreambuf_iterator::pointer</code> as return type, and this return type
may in fact be a proxy.
</p>
<p>
AFAIK, the resolution of <a href="lwg-defects.html#445" title="iterator_traits::reference unspecified for some iterator categories (Status: CD1)">445</a><sup><a href="https://cplusplus.github.io/LWG/issue445" title="Latest snapshot">(i)</a></sup> ("<code>iterator_traits::reference</code>
unspecified for some iterator categories") implies that for any iterator
class <code>Iter</code>, the return type of <code>operator-&gt;()</code> is <code>Iter::pointer</code>, by
definition.  I don't think <code>Iter::pointer</code> needs to be a raw pointer.
</p>
<p>
Still I wouldn't mind if the text "<code>operator-&gt;</code> may return a proxy" would
be removed from the resolution. I think it's up to the library
implementation, how to implement <code>istreambuf_iterator::operator-&gt;()</code>.  As
longs as it behaves as expected: <code>i-&gt;m</code> should have the same effect as
<code>(*i).m</code>. Even for an explicit destructor call, <code>i-&gt;~C()</code>.  The main issue
is just: <code>istreambuf_iterator</code> should have an <code>operator-&gt;()</code>!
</p>
</blockquote>

<p><i>[
2009-04-30 Alisdair adds:
]</i></p>


<blockquote><p>
Note that <code>operator-&gt;</code> is now a requirement in the <code>InputIterator</code> concept, so
this issue cannot be ignored or existing valid programs will break when
compiled with an 0x library.
</p></blockquote>

<p><i>[
2009-05-29 Alisdair adds:
]</i></p>


<blockquote>
<p>
I agree with the observation that in principle the type 'pointer' may be a
proxy, and the words highlighting this are redundant.
</p>
<p>
However, in the current draught <code>pointer</code> is required to be exactly '<code>charT *</code>'
by the derivation from <code>std::iterator</code>.  At a minimum, the 4th parameter of
this base class template should become unspecified.  That permits the
introduction of a proxy as a nested class in some further undocumented (not
even exposition-only) base.
</p>
<p>
It also permits the <code>istream_iterator</code> approach where the cached value is
stored in the iterator itself, and the iterator serves as its own proxy for
post-increment <code>operator++</code> - removing the need for the existing
exposition-only nested class <code>proxy</code>.
</p>
<p>
Note that the current <code>proxy</code> class also has exactly the right properties to
serve as the pointer <code>proxy</code> too.  This is likely to be a common case where an
<code>InputIterator</code> does not hold internal state but delegates to another class.
</p>
<p>
Proposed Resolution:
</p>
<p>
In addition to the current proposal:
</p>
<p>
24.6.4 <a href="https://wg21.link/istreambuf.iterator">[istreambuf.iterator]</a>
</p>
<blockquote><pre>
template&lt;class charT, class traits = char_traits&lt;charT&gt; &gt;
class istreambuf_iterator
  : public iterator&lt;input_iterator_tag, charT,
                    typename traits::off_type, <del>charT*</del> <ins><i>unspecified</i></ins>, charT&gt; {
</pre></blockquote>
</blockquote>

<p><i>[
2009-07 Frankfurt
]</i></p>


<blockquote>
<p>
Move the additional part into the proposed resolution, and wrap the
descriptive text in a Note.
</p>
<p><i>[Howard: done.]</i></p>

<p>
Move to Ready.
</p>
</blockquote>



<p id="res-659"><b>Proposed resolution:</b></p>
<p>
Add to the synopsis in 24.6.4 <a href="https://wg21.link/istreambuf.iterator">[istreambuf.iterator]</a>:
</p>

<blockquote><pre>
charT operator*() const;
<ins>pointer operator-&gt;() const;</ins>
istreambuf_iterator&lt;charT,traits&gt;&amp; operator++();
</pre></blockquote>

<p>
24.6.4 <a href="https://wg21.link/istreambuf.iterator">[istreambuf.iterator]</a>
</p>

<blockquote><pre>
template&lt;class charT, class traits = char_traits&lt;charT&gt; &gt;
class istreambuf_iterator
  : public iterator&lt;input_iterator_tag, charT,
                    typename traits::off_type, <del>charT*</del> <ins><i>unspecified</i></ins>, charT&gt; {
</pre></blockquote>

<p>
Change 24.6.4 <a href="https://wg21.link/istreambuf.iterator">[istreambuf.iterator]</a>, p1:
</p>

<blockquote><p>
The class template <code>istreambuf_iterator</code> reads successive
characters from the <code>streambuf</code> for which it was constructed.
<code>operator*</code> provides access to the current input character, if
any. <ins>[<i>Note:</i> <code>operator-&gt;</code> may return a proxy. &mdash;
<i>end note</i>]</ins> Each time
<code>operator++</code> is evaluated, the iterator advances to the next
input character. If the end of stream is reached
(<code>streambuf_type::sgetc()</code> returns <code>traits::eof()</code>), the
iterator becomes equal to the end of stream iterator value. The default
constructor <code>istreambuf_iterator()</code> and the constructor
<code>istreambuf_iterator(0)</code> both construct an end of stream iterator
object suitable for use as an end-of-range.
</p></blockquote>







</body>
</html>
