Какое значение должно возвращать `std::stringstream::fail()` после чтения и записи? (GCC против Clang)
Рассмотрим следующий фрагмент кода:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
ss << "12345";
unsigned short s;
ss >> s;
ss << "foo";
std::cout << std::boolalpha
<< "\nss.eof() = " << ss.eof()
<< "\nss.good() = " << ss.good()
<< "\nss.bad() = " << ss.bad()
<< "\nss.fail() = " << ss.fail()
<< "\nss.str() = " << ss.str();
}
Clang++ trunk выводит следующий результат:
ss.eof() = true ss.good() = false ss.bad() = false ss.fail() = false ss.str() = 12345
g ++ trunk выводит следующий результат:
ss.eof() = true ss.good() = false ss.bad() = false ss.fail() = true ss.str() = 12345
Как видите, значение ss.fail()
отличается между двумя компиляторами. Что Стандарт говорит о поведении std::stringstream
в этом случае? Это определяется реализацией, чтобы установить failbit
/badbit
при записи в поток, который уже использовался?
1 ответ
GCC правильно. std::stringstream
наследуется от std::basic_ostream
и в соответствии с поведением operator<<(std::basic_ostream)
(который вызывается изss << "foo";
),
Эффекты: ведет себя как отформатированный вставщик (как описано в [ostream.formatted.reqmts]) из out.
А из §30.7.5.2.1/1 Общие требования [ostream.formatted.reqmts]:
(акцент мой)
Каждая отформатированная выходная функция начинает выполнение с создания объекта класса sentry. Если этот объект возвращает true при преобразовании в значение типа bool, функция пытается сгенерировать запрошенный вывод.Если генерация завершится неудачно, то отформатированная функция вывода установит состояние (ios_base:: failbit), что может вызвать исключение.
И §30.7.5.1.3 Класс basic_ostream:: sentry [ostream:: sentry]:
Если os.good () не равен нулю, готовится к форматированному или неформатированному выводу. Если os.tie () не является нулевым указателем, вызывает os.tie()->flush().
Если после какой-либо подготовки os.good () имеет значение true, ok_ == true в противном случае ok_ == false. Во время подготовки конструктор может вызвать setstate (failbit) (который может выдать ios_base:: fail ([iostate.flags]))
И §30.5.5.4 basic_ios flags flags [iostate.flags]:
iostate rdstate () const;
Возвращает: состояние ошибки буфера потока.bool good () const;
Возвращает: rdstate () == 0bool eof () const;
Возвращает: true, если eofbit установлен в rdstate ().
eofbit
был установлен в этом случае, то std::basic_ios::good
возвращает ненулевое значение и вызывает ошибку записи (как показал результат), затем failbit
должен быть установлен.