Proposed resolution:
This wording is relative to N4944.
Change [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(s.rdbuf()) { } istreambuf_iterator(streambuf_type* s) noexcept; istreambuf_iterator(const proxy& p) noexcept; … private: streambuf_type* sbuf_; // exposition only int_type c_{}; // exposition only }; }
Change [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 or if sbuf_->sgetc() returns traits_type::eof().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. If s is not null, initializes c_ with s->sgetc(). Sets sbuf_ to null if sgetc exits via an exception, or if traits_type::eq_int_type(c_, traits_type::eof()) is true.
istreambuf_iterator(const proxy& p) noexcept;-4- Effects: Initializes sbuf_ with p.sbuf_. If p.sbuf_ is not null, initializes c_ with p.keep_.
Change [istreambuf.iterator.ops] as indicated:
charT operator*() const;-?- Preconditions: sbuf_ is not null.
-1- Returns:
The character obtained via the streambuf member sbuf_->sgetc().traits_type::to_char_type(c_).-?- Throws: Nothing.
istreambuf_iterator& operator++();-?- Preconditions: sbuf_ is not null.
-2- Effects:
As if by sbuf_->sbumpc().Performs c_ = sbuf_->snextc(), then sets sbuf_ to null if traits_type::eq_int_type(c_, traits_type::eof()) is true.-3- Returns: *this.
proxy operator++(int);-4-
Returns: proxy(sbuf_->sbumpc(), sbuf_).
Effects: Equivalent to:proxy p(**this, sbuf_); ++*this; return p;
bool equal(const istreambuf_iterator& b) const;-5- Returns: bool(sbuf_) == bool(b.sbuf_).
[Note: This is 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. — end note]
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;-7- Returns:
i.equal(s)i.sbuf_ == nullptr.