Details

[Home]

Issue of the Implementation # S0736

Brief

Wrong behaviour of num_get<>::do_get(bool) in the case when one target sequence is a prefix of the other one

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.

It follows from this description that if a target sequence (returned by truename() or falsename()) is a prefix of the other one, the function should continue reading from the stream after it has read the shorter target sequence. The function should do so to find if there is a unique match with the other target sequence. Only if the next character in the stream does not match the corresponding character in the longer target sequence (or if there are no more characters in the stream, in == end) should the function stop reading. The example given in the standard right after the description of do_get() demonstrates this case:

For targets true: "a" and false: "abb", the input sequence "a" yields val == true and err == str.eofbit.

If, however, the next character in the stream matches the corresponding character in the longer target sequence, the function should continue reading to determine if the input matches the longer target sequence. The fact that a part of the input coincides with the shorter target sequence should be ignored in this case. The next example from the standard demonstrates this, the target sequences for true and false being the same as above):

the input sequence "abc" yields err = str.failbit, with in ending at the 'c'.

However, the actual implementation of do_get() function sets err == str.goodbit (no error detected) and sets val to true. The remaining character sequence in the input stream is 'bc' after calling this function rather than 'c' as it should be according to the example from the standard. The sample program below demonstrates the problem.

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>
#include <algorithm>
using namespace std;

class numpunct_my : public numpunct<char>
{
public:
    numpunct_my(size_t refs = 0) : numpunct<char>(refs) {}
protected:    
    ~numpunct_my(){};
    string do_truename() const{return "a";}
    string do_falsename() const{return "abb";}
};
int main()
{
    istringstream is("abс");
    is.imbue(locale(locale(), new numpunct_my()));
    bool result = false;
    is >> boolalpha >> result;
    
    if(is.rdstate() & ios_base::failbit)
        cout << "failbit was set." << endl;
    else
        cout << "failbit wasn't set, and result is " 
             << boolalpha << result << endl;
    string rest_of_stream;
    copy((istreambuf_iterator<char>)is,
         istreambuf_iterator<char>(),
         back_insert_iterator<string>(rest_of_stream)); 
    cout << "The rest of the stream is '" << rest_of_stream << "'." << endl;
    
    return 0;
}

Component

libstdc++

Accepted

GCC Bugzilla 37957

Status

Fixed in gcc-4.4.0

[Home]