`std::stringstream::fail()` return 在读取和写入之后应该有什么值? (海湾合作委员会与铿锵声)

What value should `std::stringstream::fail()` return after reading then writing? (gcc vs 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

on wandbox


g++ trunk 打印如下结果:

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

on wandbox


如您所见,ss.fail() 的值在两个编译器之间是不同的。在这种情况下,标准对 std::stringstream 的行为有何规定?写入已消耗的流时设置 failbit/badbit 是否是实现定义的?

Gcc 是正确的。 std::stringstream 继承自 std::basic_ostream,并且根据 operator<<(std::basic_ostream) 的行为(从 ss << "foo"; 调用),

Effects: Behaves like a formatted inserter (as described in [ostream.formatted.reqmts]) of out.

来自 §30.7.5.2.1/1 Common requirements [ostream.formatted.reqmts]:

(强调我的)

Each formatted output function begins execution by constructing an object of class sentry. If this object returns true when converted to a value of type bool, the function endeavors to generate the requested output. If the generation fails, then the formatted output function does setstate(ios_­base​::​failbit), which might throw an exception.

§30.7.5.1.3 Class basic_­ostream​::​sentry [ostream::sentry]

If os.good() is nonzero, prepares for formatted or unformatted output. If os.tie() is not a null pointer, calls os.tie()->flush().

If, after any preparation is completed, os.good() is true, ok_­ == true otherwise, ok_­ == false. During preparation, the constructor may call setstate(failbit) (which may throw ios_­base​::​​failure ([iostate.flags]))

§30.5.5.4 basic_­ios flags functions [iostate.flags]

iostate rdstate() const;
Returns: The error state of the stream buffer.

bool good() const;
Returns: rdstate() == 0

bool eof() const;
Returns: true if eofbit is set in rdstate().

本例设置了

eofbit,则std::basic_ios::good returns非零,导致写入失败(结果显示),则应设置failbit