419. istream extractors not setting failbit if eofbit is already set

Section: 31.7.5.2.4 [istream.sentry] Status: C++11 Submitter: Martin Sebor Opened: 2003-09-18 Last modified: 2021-06-06

Priority: Not Prioritized

View all other issues in [istream.sentry].

View all issues with C++11 status.

Discussion:

[istream::sentry], p2 says that istream::sentry ctor prepares for input if is.good() is true. p4 then goes on to say that the ctor sets the sentry::ok_ member to true if the stream state is good after any preparation. 31.7.5.3.1 [istream.formatted.reqmts], p1 then says that a formatted input function endeavors to obtain the requested input if the sentry's operator bool() returns true. Given these requirements, no formatted extractor should ever set failbit if the initial stream rdstate() == eofbit. That is contrary to the behavior of all implementations I tested. The program below prints out

eof = 1, fail = 0
eof = 1, fail = 1

on all of them.


#include <sstream>
#include <cstdio>

int main()
{
    std::istringstream strm ("1");

    int i = 0;

    strm >> i;

    std::printf ("eof = %d, fail = %d\n",
                 !!strm.eof (), !!strm.fail ());

    strm >> i;

    std::printf ("eof = %d, fail = %d\n",
                 !!strm.eof (), !!strm.fail ());
}


Comments from Jerry Schwarz (c++std-lib-11373):
Jerry Schwarz wrote:
I don't know where (if anywhere) it says it in the standard, but the formatted extractors are supposed to set failbit if they don't extract any characters. If they didn't then simple loops like
while (cin >> x);
would loop forever.
Further comments from Martin Sebor:
The question is which part of the extraction should prevent this from happening by setting failbit when eofbit is already set. It could either be the sentry object or the extractor. It seems that most implementations have chosen to set failbit in the sentry [...] so that's the text that will need to be corrected.

Pre Berlin: This issue is related to 342. If the sentry sets failbit when it finds eofbit already set, then you can never seek away from the end of stream.

Kona: Possibly NAD. If eofbit is set then good() will return false. We then set ok to false. We believe that the sentry's constructor should always set failbit when ok is false, and we also think the standard already says that. Possibly it could be clearer.

[ 2009-07 Frankfurt ]

Moved to Ready.

Proposed resolution:

Change [istream::sentry], p2 to:

explicit sentry(basic_istream<charT,traits>& is , bool noskipws = false);

-2- Effects: If is.good() is true false, calls is.setstate(failbit). Otherwise prepares for formatted or unformatted input. ...