c++gccclangiostreammanipulators

Should std::ws raise failbit at end of file?


Should extracting from a stream using the std::ws manipulator ever raise the fail bit? In the following code, a Clang-compiled (within Xcode 4.5.1) program fails the final assertion. Evidently s >> std::ws at EOF causes a fail. Yet GCC 4.7.2 passes the assertion. Which is correct?

#include <iostream>
#include <sstream>
#include <cassert>

int main(int argc, const char * argv[])
{
    {
        // Read string with trailing ws.
        std::istringstream s( "test   " );
        std::string test;

        s >> std::ws;
        assert( !s.fail() );    // No ws to skip, but no failure.

        s >> test;
        assert( test == "test" );
        assert( !s.fail() );

        s >> std::ws;
        assert( !s.fail() );    // No prob skipping trailing ws.
    }
    {
        // Retry with no trailing ws.
        std::istringstream s( "test" );
        std::string test;

        s >> std::ws;
        assert( !s.fail() );    // No ws to skip, but no failure.

        s >> test;
        assert( test == "test" );
        assert( !s.fail() );

        s >> std::ws;
        assert( !s.fail() );    // CLANG: Skipping absent ws at eof raises failbit.
    }

    return 0;
}

Solution

  • C++11, §27.7.2.4/1:

    If ws stops extracting characters because there are no more available it sets eofbit, but not failbit.

    So, the ws manipulator doesn't set failbit directly. However, as Marshall Clow points out in his answer, it doesn't have to--it is required to create a sentry object, and the sentry object is required to set the failbit if !stream.good().