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

### 2544. `istreambuf_iterator(basic_streambuf<charT, traits>* s)` effects unclear when `s` is `0`

Section: 23.6.4.3 [istreambuf.iterator.cons] Status: C++17 Submitter: S. B. Tam Opened: 2015-10-05 Last modified: 2017-07-30

Priority: 3

View all issues with C++17 status.

Discussion:

N4527 23.6.4.3 [istreambuf.iterator.cons] does not mention what the effect of calling `istreambuf_iterator(basic_streambuf<charT, traits>* s)` is when `s` is a null pointer. It should be made clear that this case is well-formed and the result is a end-of-stream iterator.

Daniel:

According to 23.6.4 [istreambuf.iterator] p1:

> […] 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. […]

This indicates that the described constructor creates an end-of-stream iterator, but this wording is part of the introductory wording and I recommend to make 23.6.4.3 [istreambuf.iterator.cons] clearer, because the existing specification is already flawed, e.g. it never specifies when and how the exposition-only-member `sbuf_` is initialized. The proposed wording below attempts to solve these problems as well.

Previous resolution [SUPERSEDED]:

> This wording is relative to N4527.

> 1. Change 23.6.4.3 [istreambuf.iterator.cons] as indicated:

>    [Editorial note: The proposed wording changes also performs some editorial clean-up of the existing mismatches of the declarations in the class template synopsis and the individual member specifications. The below wording intentionally does not say anything about the concrete value of `sbuf_` for end-of-stream iterator values, because that was never specified before; in theory, this could be some magic non-null pointer that can be used in constant expressions. But the wording could be drastically simplified by requiring `sbuf_` to be a null pointer for an end-of-stream iterator value, since I have not yet seen any implementation where this requirement does not hold. — end editorial note]

>    >     constexpr istreambuf_iterator() noexcept;

>    > > -1- Effects: Constructs the end-of-stream iterator.

>    >     istreambuf_iterator(basic_istream<charT,traits>istream_type& s) noexcept;
>    >     istreambuf_iterator(basic_streambuf<charT,traits>* s) noexcept;

>    > > -2- Effects: If `s.rdbuf()` is a null pointer, constructs an end-of-stream iterator; otherwise initializes `sbuf_` with `s.rdbuf()` and constructs an `istreambuf_iterator` that uses the `streambuf_type` object `*sbuf_`Constructs an `istreambuf_iterator<>` that uses the `basic_streambuf<>` object `*(s.rdbuf())`, or `*s`, respectively. Constructs an end-of-stream iterator if `s.rdbuf()` is null.

>    >     istreambuf_iterator(streambuf_type* s) noexcept;

>    > > -?- Effects: If `s` is a null pointer, constructs an end-of-stream iterator; otherwise initializes `sbuf_` with `s` and constructs an `istreambuf_iterator` that uses the `streambuf_type` object `*sbuf_`.

>    >     istreambuf_iterator(const proxy& p) noexcept;

>    > > -3- Effects: Initializes `sbuf_` with `p.sbuf_` and constructs an `istreambuf_iterator` that uses the `streambuf_type` object `*sbuf_`Constructs a `istreambuf_iterator<>` that uses the `basic_streambuf<>` object pointed to by the `proxy` object's constructor argument `p`.

[2015-10-20, Daniel provides alternative wording]

[2016-08-03 Chicago]

Fri AM: Moved to Tentatively Ready

Proposed resolution:

This wording is relative to N4606.

1. Change 23.6.4.3 [istreambuf.iterator.cons] as indicated:

   > [Drafting note: The proposed wording changes also performs some editorial clean-up of the existing mismatches of the declarations in the class template synopsis and the individual member specifications. The below wording is simplified by requiring `sbuf_` to be a null pointer for an end-of-stream iterator value, since I have not yet seen any implementation where this requirement does not hold. Even if there were such an implementation, this would still be conforming, because concrete exposition-only member values are not part of public API. — end drafting note]

   > For each `istreambuf_iterator` constructor in this section, an end-of-stream iterator is constructed if and only if the exposition-only member `sbuf_` is initialized with a null pointer value.

   >     constexpr istreambuf_iterator() noexcept;

   > > -1- Effects: Initializes `sbuf_` with `nullptr` Constructs the end-of-stream iterator.

   >     istreambuf_iterator(basic_istream<charT,traits>istream_type& s) noexcept;
   >     istreambuf_iterator(basic_streambuf<charT,traits>* s) noexcept;

   > > -2- Effects: Initializes `sbuf_` with `s.rdbuf()`Constructs an `istreambuf_iterator<>` that uses the `basic_streambuf<>` object `*(s.rdbuf())`, or `*s`, respectively. Constructs an end-of-stream iterator if `s.rdbuf()` is null.

   >     istreambuf_iterator(streambuf_type* s) noexcept;

   > > -?- Effects: Initializes `sbuf_` with `s`.

   >     istreambuf_iterator(const proxy& p) noexcept;

   > > -3- Effects: Initializes `sbuf_` with `p.sbuf_`Constructs a `istreambuf_iterator<>` that uses the `basic_streambuf<>` object pointed to by the `proxy` object's constructor argument `p`.