Details

[Home]

Issue of the Implementation # S0735

Brief

num_get<>::do_get(bool) sets eofbit flag incorrectly when boolalpha == true

Detailed Description

The description of the function

iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const

states the following for the case when

(str.flags() & ios_base::boolalpha) != 0 (22.2.2.1.2):

(p15)Otherwise target sequences are determined "as if" by calling the members falsename() and truename() of the facet obtained by use_facet<numpunct<charT> >(str.getloc()). Successive characters in the range [in,end) (see 23.1.1) are obtained and matched against corresponding positions in the target sequences only as necessary to identify a unique match. The input iterator in is compared to end only when necessary to obtain a character. If and only if a target sequence is uniquely matched, val is set to the corresponding value.

Therefore, the comparison of 'in' and 'end' iterators should take place if and only if the sequence read so far using (*in++) equals neither of the target sequences (returned by truename() and falsename()) but may become equal in the future as more characters are read.
Particularly, assume truename() returns "true" and falsename() returns "false". Once 't', 'r', 'u', 'e' symbols have been read from the stream, there will be no further comparison of 'in' and 'end' even though 'in' may equal 'end' at the moment.

(p16)The in iterator is always left pointing one position beyond the last character successfully matched. If val is set, then err is set to str.goodbit; or to str.eofbit if, when seeking another character to match, it is found that (in == end). If val is not set, then err is set to str.failbit; or to (str.failbit|str.eofbit) if the reason for the failure was that (in == end).

It follows from the above that the 'eofbit' flag is set if and only if 'in' happened to equal 'end' during the reading of the sequence from the stream. Note that this is not the same as if 'in' was equal to 'end' after the sequence has been read. The actual implementation, however, behaves in a different way. It sets the 'eofbit' flag if just before return from the function in == end. That is, the comparison takes place after the sequence has been read and matched (or not matched).

This results, for instance, in setting a wrong value of 'err' in the following examples given in the standard right after the description of do_get() function (22.2.2.1.2 p16):

For targets true: "1" and false: "0", the input sequence "1" yields val == true and err == str.goodbit. For empty targets (""), any input sequence yields err == str.failbit.

In practice, the implementation sets err = str.eofbit in the first case and err = str.failbit | str.eofbit in the second one (when the stream is empty, that is, originally in == end).

The example below demonstrated the behaviour of the function when the strings "true" and "false" correspond to true and false, respectively and the input sequence is "true".
According to the standard, 'eofbit' flag should not be set but it is, actually.

Problem location(s) in the standard

Linux Standard Base C++ Specification 3.2, Chapter 9. Libraries, 9.1. Interfaces for libstdcxx that refers ISO/IEC 14882: 2003 Programming languages --C++, section 22.2.2.1.2

Example

#include <iostream>
#include <sstream>
using namespace std;

int main()
{
    istringstream is("true");
    bool result;
    is >> boolalpha >> result;
    
    if(is.rdstate() & ios_base::eofbit)
        cout << "eofbit was set." << endl;
    else
        cout << "eofbit wasn't set." << endl;
    return 0;
}

Component

libstdc++

Accepted

GCC Bugzilla 37958

Status

Fixed in gcc-4.4.0

[Home]