代码之家  ›  专栏  ›  技术社区  ›  Vittorio Romeo

读写之后,'std::stringstream::fail()`应该返回什么值?(gcc vs clang)

  •  8
  • Vittorio Romeo  · 技术社区  · 7 年前

    考虑以下代码段:

    #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 当写入已经消耗的流时?

    1 回复  |  直到 7 年前
        1
  •  4
  •   songyuanyao    7 年前

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

    效果:其行为类似于out的格式化插入器(如[ostream.formatted.reqmts]中所述)。

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

    (强调矿山)

    每个格式化输出函数通过构造sentry类的对象开始执行。如果此对象在转换为bool类型的值时返回true,则函数将努力生成请求的输出。 如果生成失败,则格式化输出函数会设置状态(ios\u base::failbit)

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

    如果操作系统。good()为非零,准备格式化或未格式化的输出。 如果操作系统。tie()不是空指针,调用os。连接()->刷新()。

    如果在任何准备工作完成后。good()是真的,ok\u== 否则,ok_==false。在准备过程中,建造商可以 调用设置状态(failbit)(可能引发ios_base::failure ([iostate.flags]))

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


    返回:流缓冲区的错误状态。

    布尔良()常数;
    返回:rdstate()==0

    布尔eof()常数;
    如果在rdstate()中设置了eofbit,则返回true。

    eofbit 在这种情况下已经设置,那么 std::basic_ios::good 返回非零并导致写入失败(如结果所示),然后 failbit 应设置。