Подробности
[В начало]
Проблема в реализации № S0736
Краткое описание
num_get<>::do_get(bool) неверно работает в случае, когда одна целевая последовательность является префиксом другой
Подробное описание
Из описания функции
iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const
для случая (str.flags() & ios_base::boolalpha) != 0 (22.2.2.1.2, p15):
Отсюда следует, что когда одна целевая последовательность (truename() или falsename()) является префиксом другой, прочитав меньшую последовательность из потока, функция должна продолжить чтение - чтобы найти уникальное соответствие (unique match). И только в случае, когда следующий символ в потоке не соответствует символу в большей последовательности (или когда в потоке нет больше символов, in == end), функция прерывает чтение. Этому случаю соответствует пример, приведеный в стандарте после описания функции do_get():
For targets true: "a" and false: "abb", the input sequence "a" yields val == true and err == str.eofbit.Однако если следующий символ в потоке соответствует большей целевой последовательности, то функция должна продолжить чтение потока и проверить, что входная последовательность соответствует большей целевой последовательности. При этом факт совпадения части входной последовательности и меньшей целевой последовательности не играет роли. Этому случаю соответствует следующий пример из стандарта (при тех же строках, соответствующих true и false):
the input sequence "abc" yields err = str.failbit, with in ending at the ’c’.Однако реализация в этом случае возвращает err==str.goodbit (нет ошибки), при этом в val записывается значение true. Содержимое потока после вызова функции - 'bc', а не 'c', как указано в примере. Это и демонстрирует приведённый ниже пример.
Раздел стандарта
Linux Standard Base C++ Specification 3.2, Chapter 9. Libraries, 9.1. Interfaces for libstdcxx, который ссылается на ISO/IEC 14882: 2003 Programming languages --C++, section 22.2.2.1.2
Пример
#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; }
Компонент
libstdc++
Принято
GCC Bugzilla 37957
Статус
Исправлено в gcc-4.4.0
[В начало]