Are there cases where the last operation succeeds but the istream/ostream goes fail()?

Viewed 41

I'm a new learner of C++. In my understanding, fail() indicates whether the last operation on the istream/ostream succeeded or not. For example, let ifs be an ifstream opened to some valid file:

string s;
while (ifs >> s) {
    // 1. assume the reading was taken successfully
    //    and do something according to that
}
// 2. assume the reading was unsuccessful
//    and do something according to that

May I ask if it is possible that, in some (corner) cases, we arrive at 2. while the reading was actually successfully taken?

If so, what we do at 2. could be problematic. For example, if we have set ifs.exceptions(ifs.exceptions() | ios_base::badbit);, then we would (probably) have assumed that ifs is empty at 2..


I came up with this question when I was self-learning C++ using Stroustrup's book Programming: Principle and Practice Using C++ (2nd ed.). In Chapter 11.7 of this book, the writers design a Punct_stream class that takes an istream as source, processes data extracted from the source and then put the processed data into a data member of type istringstream called buffer waiting to be inputted into the program. The writers design the operator bool() method as follows (Page 404):

Punct_stream::operator bool()
{
    return !(source.fail() || source.bad()) && buffer.good();
}

Firstly, I think !(source.fail() || source.bad()) should be equivalent to just checking source since fail() accounts for both failbit and badbit, and checking source is equivalent to checking !fail().

What is more related to my question is that, by this design, operator bool() will first check if the source is in an error state, and if so, it won't even look at the buffer. But reading data from a Punct_stream into a string will be done as long as there is character in buffer. So, if the buffer is not empty and the source is fail() somehow, then reading from the Punct_stream into a string will actually succeed while the checking on the Punct_stream condition will be false.

I wonder if the implementation of the standard library istreams may behave in some similar way such that in some cases the reading is actually successfully taken but the condition is evaluated to false?

1 Answers

All iostream input functions start by creating a sentry object which checks the good state of the stream. If the state is not good (that is any of badbit, eof or failbit is set), then the sentry will set the failbit and return false, which will cause the input function to immediately return without reading anything, without modifying (or even checking) the streambuffer, and without writing anything into the destination of the input function.

So by definition, if the stream test in the while is false, it must have either been false or eof before (and nothing was read into the string s), or it failed to be able to read anything into the string and it set the state to false. In either case, nothing was read into the string.

Related