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

### 342. seek and eofbit

Section: 29.7.4.4 [istream.unformatted] Status: NAD Submitter: Howard Hinnant Opened: 2001-10-09 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [istream.unformatted].

View all issues with NAD status.

Discussion:

I think we have a defect.

According to lwg issue 60 which is now a dr, the description of seekg in 29.7.4.4 [istream.unformatted] paragraph 38 now looks like:

> Behaves as an unformatted input function (as described in 27.6.1.3, paragraph 1), except that it does not count the number of characters extracted and does not affect the value returned by subsequent calls to gcount(). After constructing a sentry object, if fail() != true, executes rdbuf()->pubseekpos( pos).

And according to lwg issue 243 which is also now a dr, 27.6.1.3, paragraph 1 looks like:

> Each unformatted input function begins execution by constructing an object of class sentry with the default argument noskipws (second) argument true. If the sentry object returns true, when converted to a value of type bool, the function endeavors to obtain the requested input. Otherwise, if the sentry constructor exits by throwing an exception or if the sentry object returns false, when converted to a value of type bool, the function returns without attempting to obtain any input. In either case the number of extracted characters is set to 0; unformatted input functions taking a character array of non-zero size as an argument shall also store a null character (using charT()) in the first location of the array. If an exception is thrown during input then ios::badbit is turned on in *this'ss error state. If (exception()&badbit)!= 0 then the exception is rethrown. It also counts the number of characters extracted. If no exception has been thrown it ends by storing the count in a member object and returning the value specified. In any event the sentry object is destroyed before leaving the unformatted input function.

And finally 27.6.1.1.2/5 says this about sentry:

> If, after any preparation is completed, is.good() is true, ok_ != false otherwise, ok_ == false.

So although the seekg paragraph says that the operation proceeds if !fail(), the behavior of unformatted functions says the operation proceeds only if good(). The two statements are contradictory when only eofbit is set. I don't think the current text is clear which condition should be respected.

Further discussion from Redmond:

PJP: It doesn't seem quite right to say that `seekg` is "unformatted". That makes specific claims about sentry that aren't quite appropriate for seeking, which has less fragile failure modes than actual input. If we do really mean that it's unformatted input, it should behave the same way as other unformatted input. On the other hand, "principle of least surprise" is that seeking from EOF ought to be OK.

Pre-Berlin: Paolo points out several problems with the proposed resolution in Ready state:

- It should apply to both overloads of seekg.
- tellg has similar issues, except that it should not call clear().
- The point about clear() seems to apply to seekp().
- Depending on the outcome of 419 if the sentry sets `failbit` when it finds `eofbit` already set, then you can never seek away from the end of stream.

[ 2009-07 Frankfurt ]

> Moved to NAD. Will reopen if proposed resolution is supplied.

Proposed resolution:

Change 29.7.4.4 [istream.unformatted] to:

> Behaves as an unformatted input function (as described in 27.6.1.3, paragraph 1), except that it does not count the number of characters extracted, does not affect the value returned by subsequent calls to gcount(), and does not examine the value returned by the sentry object. After constructing a sentry object, if `fail() != true`, executes `rdbuf()->pubseekpos(pos)`. In case of success, the function calls clear(). In case of failure, the function calls `setstate(failbit)` (which may throw `ios_base::failure`).

[Lillehammer: Matt provided wording.]

Rationale:

In C, fseek does clear EOF. This is probably what most users would expect. We agree that having eofbit set should not deter a seek, and that a successful seek should clear eofbit. Note that `fail()` is true only if `failbit` or `badbit` is set, so using `!fail()`, rather than `good()`, satisfies this goal.