Какое значение должно возвращать `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

на wandbox


g ++ trunk выводит следующий результат:

ss.eof()  = true
ss.good() = false
ss.bad()  = false
ss.fail() = true
ss.str()  = 12345

на wandbox


Как видите, значение 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 () == 0

bool eof () const;
Возвращает: true, если eofbit установлен в rdstate ().

eofbit был установлен в этом случае, то std::basic_ios::good возвращает ненулевое значение и вызывает ошибку записи (как показал результат), затем failbit должен быть установлен.

Другие вопросы по тегам