Section: 25.6.4 [istreambuf.iterator] Status: New Submitter: Hyman Rosen Opened: 2014-02-19 Last modified: 2023-04-13 07:33:55 UTC
View other active issues in [istreambuf.iterator].
View all other issues in [istreambuf.iterator].
View all issues with New status.
Given the following code,
#include <sstream> std::stringbuf buf; std::istreambuf_iterator<char> begin(&buf); std::istreambuf_iterator<char> end;
it is not clear from the wording of the Standard whether begin.equal(end) must be true. In at least one implementation it is not (CC: Sun C++ 5.10 SunOS_sparc Patch 128228-25 2013/02/20) and in at least one implementation it is (gcc version 4.3.2 x86_64-unknown-linux-gnu).25.6.4 [istreambuf.iterator] says that end is an end-of-stream iterator since it was default constructed. It also says that an iterator becomes equal to an end-of-stream iterator when end of stream is reached by sgetc() having returned eof(). [istreambuf.iterator::equal] says that equal() returns true iff both iterators are end of stream or not end of stream. But there seems to be no requirement that equal check for end-of-stream by calling sgetc(). Jiahan Zi at BloombergLP discovered this issue through his code failing to work correctly. Dietmar Kühl has opined in a private communication that the iterators should compare equal.
[2023-03-31; Jonathan Wakely comments]
I agree that they should compare equal, but that's in conflict with the
resolution of LWG 2544, which says that
must not be at end-of-stream because
&buf is not null.
[2023-04-12; Jonathan adds wording]
This wording is relative to N4944.
Change 22.214.171.124 [istreambuf.iterator.general] as indicated:
constexpr istreambuf_iterator() noexcept; constexpr istreambuf_iterator(default_sentinel_t) noexcept; istreambuf_iterator(const istreambuf_iterator&) noexcept = default; ~istreambuf_iterator() = default; istreambuf_iterator(istream_type& s) noexcept
;istreambuf_iterator(streambuf_type* s) noexcept; istreambuf_iterator(const proxy& p) noexcept; … private: streambuf_type* sbuf_; // exposition only }; }
Change 126.96.36.199 [istreambuf.iterator.cons] as indicated:
For each istreambuf_iterator constructor in this section, an end-of-stream iterator is constructed if
and only ifthe exposition-only member sbuf_ is initialized with a null pointer value .constexpr istreambuf_iterator() noexcept; constexpr istreambuf_iterator(default_sentinel_t) noexcept;
-1- Effects: Initializes sbuf_ with nullptr.
istreambuf_iterator(istream_type& s) noexcept;
-2- Effects: Initializes sbuf_ with s.rdbuf().istreambuf_iterator(streambuf_type* s) noexcept;
[Drafting note: sgetc() can throw, but this function is noexcept. Should it swallow exceptions and create an end-of-stream iterator, to avoid weakening the exception spec of an existing function?]
-3- Effects: Initializes sbuf_ with s.istreambuf_iterator(const proxy& p) noexcept;
-4- Effects: Initializes sbuf_ with p.sbuf_.
Change 188.8.131.52 [istreambuf.iterator.ops] as indicated:
charT operator*() const;
The character obtained via the streambuf member sbuf_->sgetc().
As if by sbuf_->sbumpc().
-3- Returns: *this.proxy operator++(int);
Returns: proxy(sbuf_->sbumpc(), sbuf_).
bool equal(const istreambuf_iterator& b) const;
true if and only if both iterators are at end-of-stream, or neither is at end-of-stream, regardless of what streambuf object they use.template<class charT, class traits> bool operator==(const istreambuf_iterator<charT, traits>& a, const istreambuf_iterator<charT, traits>& b);
-6- Returns: a.equal(b).bool equal(const istreambuf_iterator& i, default_sentinel_t s) const;