This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 659. `istreambuf_iterator` should have an `operator->()`

Section: 23.6.4 [istreambuf.iterator] Status: C++11 Submitter: Niels Dekker Opened: 2007-03-25 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [istreambuf.iterator].

View all other issues in [istreambuf.iterator].

View all issues with C++11 status.

Discussion:

Greg Herlihy has clearly demonstrated that a user defined input iterator should have an `operator->()`, even if its value type is a built-in type (comp.std.c++, "Re: Should any iterator have an `operator->()` in C++0x?", March 2007). And as Howard Hinnant remarked in the same thread that the input iterator `istreambuf_iterator` doesn't have one, this must be a defect!

Based on Greg's example, the following code demonstrates the issue:

     #include <iostream>
     #include <fstream>
     #include <streambuf>

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

       (*i).~C();  // This is well-formed...
       i->~C();  // ... so this should be supported!
     }

Of course, `operator->` is also needed when the `value_type` of `istreambuf_iterator` is a class.

The `operator->` 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 `operator_arrow_proxy`, from http://www.boost.org/boost/iterator/iterator_facade.hpp

I hope that the resolution of this issue will contribute to getting a clear and consistent definition of iterator concepts.

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

[ Niels Dekker (mailed to Howard Hinnant): ]

> The proposed resolution does not seem inconsistent to me. `istreambuf_iterator::operator->()` should have `istreambuf_iterator::pointer` as return type, and this return type may in fact be a proxy.

> AFAIK, the resolution of 445 ("`iterator_traits::reference` unspecified for some iterator categories") implies that for any iterator class `Iter`, the return type of `operator->()` is `Iter::pointer`, by definition. I don't think `Iter::pointer` needs to be a raw pointer.

> Still I wouldn't mind if the text "`operator->` may return a proxy" would be removed from the resolution. I think it's up to the library implementation, how to implement `istreambuf_iterator::operator->()`. As longs as it behaves as expected: `i->m` should have the same effect as `(*i).m`. Even for an explicit destructor call, `i->~C()`. The main issue is just: `istreambuf_iterator` should have an `operator->()`!

[ 2009-04-30 Alisdair adds: ]

> Note that `operator->` is now a requirement in the `InputIterator` concept, so this issue cannot be ignored or existing valid programs will break when compiled with an 0x library.

[ 2009-05-29 Alisdair adds: ]

> I agree with the observation that in principle the type 'pointer' may be a proxy, and the words highlighting this are redundant.

> However, in the current draught `pointer` is required to be exactly '`charT *`' by the derivation from `std::iterator`. 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.

> It also permits the `istream_iterator` approach where the cached value is stored in the iterator itself, and the iterator serves as its own proxy for post-increment `operator++` - removing the need for the existing exposition-only nested class `proxy`.

> Note that the current `proxy` class also has exactly the right properties to serve as the pointer `proxy` too. This is likely to be a common case where an `InputIterator` does not hold internal state but delegates to another class.

> Proposed Resolution:

> In addition to the current proposal:

> 23.6.4 [istreambuf.iterator]

> >     template<class charT, class traits = char_traits<charT> >
> >     class istreambuf_iterator
> >       : public iterator<input_iterator_tag, charT,
> >                         typename traits::off_type, charT* unspecified, charT> {

[ 2009-07 Frankfurt ]

> Move the additional part into the proposed resolution, and wrap the descriptive text in a Note.

> [Howard: done.]

> Move to Ready.

Proposed resolution:

Add to the synopsis in 23.6.4 [istreambuf.iterator]:

>     charT operator*() const;
>     pointer operator->() const;
>     istreambuf_iterator<charT,traits>& operator++();

23.6.4 [istreambuf.iterator]

>     template<class charT, class traits = char_traits<charT> >
>     class istreambuf_iterator
>       : public iterator<input_iterator_tag, charT,
>                         typename traits::off_type, charT* unspecified, charT> {

Change 23.6.4 [istreambuf.iterator], p1:

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