istreambuf_iterator
should have an operator->()
Section: 24.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 haveistreambuf_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 classIter
, the return type ofoperator->()
isIter::pointer
, by definition. I don't thinkIter::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 implementistreambuf_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 anoperator->()
!
[ 2009-04-30 Alisdair adds: ]
Note that
operator->
is now a requirement in theInputIterator
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 fromstd::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-incrementoperator++
- removing the need for the existing exposition-only nested classproxy
.Note that the current
proxy
class also has exactly the right properties to serve as the pointerproxy
too. This is likely to be a common case where anInputIterator
does not hold internal state but delegates to another class.Proposed Resolution:
In addition to the current proposal:
24.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 24.6.4 [istreambuf.iterator]:
charT operator*() const; pointer operator->() const; istreambuf_iterator<charT,traits>& operator++();
24.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 24.6.4 [istreambuf.iterator], p1:
The class template
istreambuf_iterator
reads successive characters from thestreambuf
for which it was constructed.operator*
provides access to the current input character, if any. [Note:operator->
may return a proxy. — end note] Each timeoperator++
is evaluated, the iterator advances to the next input character. If the end of stream is reached (streambuf_type::sgetc()
returnstraits::eof()
), the iterator becomes equal to the end of stream iterator value. The default constructoristreambuf_iterator()
and the constructoristreambuf_iterator(0)
both construct an end of stream iterator object suitable for use as an end-of-range.