I've just reviewed both the libc++ implementation and the parts of the standard which specifies this behavior:
27.7.2.1 Class template basic_istream [istream]/p3:
If
rdbuf()->sbumpc()
orrdbuf()->sgetc()
returnstraits::eof()
, then the input function, except as explicitly noted otherwise, completes its actions and doessetstate(eofbit)
, which may throwios_base::failure
(27.5.5.4), before returning.
And then p4:
If one of these called functions throws an exception, then unless explicitly noted otherwise, the input function sets
badbit
in error state. Ifbadbit
is on inexceptions()
, the input function rethrows the exception without completing its actions, otherwise it does not throw anything and proceeds as if the called function had returned a failure indication.
I believe the crux here is the interpretation of "one of these called functions." I interpreted that phrase to refer to all of the functions mentioned in the preceding paragraph, including setstate(eofbit)
. Under that interpretation, libc++'s behavior is correct since badbit
is not set.
To get the behavior you desire, do:
is.exceptions(std::ios::eofbit | std::ios::failbit | std::ios::badbit);