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

### 2349. Clarify input/output function rethrow behavior

Section: 31.7.5.3.1 [istream.formatted.reqmts] Status: Resolved Submitter: Zhihao Yuan Opened: 2013-12-06 Last modified: 2022-11-22

Priority: 3

View all other issues in [istream.formatted.reqmts].

View all issues with Resolved status.

Discussion:

The formatted input function requirement says in 31.7.5.3.1 [istream.formatted.reqmts]:

> "If an exception is thrown during input then `ios::badbit` is turned on in `*this`'s error state. If `(exceptions()&badbit) != 0` then the exception is rethrown."

while some formatted function may throw an exception from `basic_ios::clear`, for example in 22.9.4 [bitset.operators] p6:

> "If no characters are stored in `str`, calls `is.setstate(ios_base::failbit)` (which may throw `ios_base::failure`)"

So should this exception be considered as "an exception [...] thrown during input"? And here is an implementation divergence (or you can read the following as "a bug libc++ only has" :)

>     cin.exceptions(ios_base::failbit);
>     bitset<N> b;
>     try {
>       cin >> b;  // type 'a' and return
>     } catch (...)
>     {}

Now `cin.rdstate()` is just `failbit` in libstdc++ (and Dinkumware, by PJ), but `failbit & badbit` libc++. Similar difference found in other places, like `eofbit & badbid` after `std::getline`.

PJ and Matt both agree that the intention (of `badbit` + rethrow) is "to signify an exception arising in user code, not the iostreams package".

In addition, I found the following words in unformatted input function's requirements (31.7.5.4 [istream.unformatted]):

> If an exception is thrown during input then `ios::badbit` is turned on in `*this`'s error state. (Exceptions thrown from `basic_ios<>::clear()` are not caught or rethrown.) If `(exceptions()&badbit) != 0` then the exception is rethrown.

The content within the parenthesis is added by LWG defect 61, and does fix the ambiguity. However, it only fixed the 1 of 4 requirements, and it lost some context (the word "rethrown" is not seen before this sentence within this section).

[Lenexa 2015-05-07: Marshall to research and report]

[Kona 2022-11-08; this would be resolved by P1264]

[2022-11-22 Resolved by P1264R2 accepted in Kona. Status changed: Open → Resolved.]

Proposed resolution:

This wording is relative to N3797.

[Drafting note: The editor is kindly asked to introduce additional spaces at the following marked occurrences of `operator&` — end drafting note]

1. Modify 31.7.5.3.1 [istream.formatted.reqmts] p1 as indicated:

   > -1- Each formatted input function begins execution by constructing an object of class `sentry` with the `noskipws` (second) argument false. If the `sentry` object returns true, when converted to a value of type `bool`, the function endeavors to obtain the requested input. If an exception, other than the ones thrown from `clear()`, if any, is thrown during input then `ios::badbit` is turned on[Footnote 314] in `*this`'s error state. If `(exceptions() & badbit) != 0` then the exception is rethrown. In any case, the formatted input function destroys the `sentry` object. If no exception has been thrown, it returns `*this`.

2. Modify 31.7.6.3.1 [ostream.formatted.reqmts] p1 as indicated:

   > -1- Each formatted output function begins execution by constructing an object of class `sentry`. If this object returns true when converted to a value of type `bool`, the function endeavors to generate the requested output. If the generation fails, then the formatted output function does `setstate(ios_base::failbit)`, which might throw an exception. If an exception, other than the ones thrown from `clear()`, if any, is thrown during output, then `ios::badbit` is turned on[Footnote 327] in `*this`'s error state. If `(exceptions() & badbit) != 0` then the exception is rethrown. Whether or not an exception is thrown, the `sentry` object is destroyed before leaving the formatted output function. If no exception is thrown, the result of the formatted output function is `*this`.

3. Modify 31.7.6.4 [ostream.unformatted] p1 as indicated:

   > -1- Each unformatted output function begins execution by constructing an object of class `sentry`. If this object returns true, while converting to a value of type `bool`, the function endeavors to generate the requested output. If an exception, other than the ones thrown from `clear()`, if any, is thrown during output, then ios::badbit is turned on[Footnote 330] in `*this`'s error state. If `(exceptions() & badbit) != 0` then the exception is rethrown. In any case, the unformatted output function ends by destroying the `sentry` object, then, if no exception was thrown, returning the value specified for the unformatted output function.

4. Modify 31.7.5.4 [istream.unformatted] p1 as indicated:

   > -1- 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, other than the ones thrown from `clear()`, if any, is thrown during input then `ios::badbit` is turned on[Footnote 317] in `*this`'s error state. (Exceptions thrown from `basic_ios<>::clear()` are not caught or rethrown.) If `(exceptions() & 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.