C++ 方法 ostream::exceptions(iostate state) 的行为应该是什么?

What is the behavior of the C++ method ostream::exceptions(iostate state) supposed to be?

我正在编写我自己的输出流媒体库,并且我正在尝试模仿 std::ostream 与我试图实现的新行为不冲突的行为。目前我正在尝试模仿这个继承自 ios:

的接口
std::ostream::exceptions(ios::iostate state)

根据cplusplus.com

"this method sets a new exception mask for the stream and clears the stream's error state flags (as if member clear() was called)."

我不清楚这是否意味着所有标志都将被清除,还是仅清除异常掩码中设置的标志,因此我编写了一个测试程序,但得到了意想不到的结果。这是程序:

#include <sstream>
#include <iostream>

using namespace std;
int main(int argc, char** argv)
{
    ostringstream oss;
    try
    {
        cout << "            badbit           = " << ios::badbit        << "\n";
        cout << "            eofbit           = " << ios::eofbit        << "\n";
        cout << "            failbit          = " << ios::failbit       << "\n\n";

        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n\n";

        cout << "executing:  oss.setstate(ios::badbit | ios::failbit);" << "\n";
        oss.setstate(ios::badbit | ios::failbit);
        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n\n";

        cout << "executing:  oss.exceptions(ios::failbit);"             << "\n";
        oss.exceptions(ios::failbit);
        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n";
    }
    catch(const exception& x)
    {
        cout << endl;
        cout << "**** EXCEPTION THROWN ****"                            << "\n";
        cout << argv[0] << ":  " << x.what() << endl;
        cout << "            oss.rdstate()    = " << oss.rdstate()      << "\n";
        cout << "            oss.exceptions() = " << oss.exceptions()   << "\n";
        return 1;
    }
    catch(...)
    {
        cerr << argv[0] << ":  unknown exception." << endl;
        return 1;
    }
    return 0;
}

这是输出:

matt@dworkin:~/dev/ostream/libs/ostream$ g++ --version
g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

matt@dworkin:~/dev/ostream/libs/ostream$ g++ --std=c++17 foo.cpp
matt@dworkin:~/dev/ostream/libs/ostream$ ./a.out

            badbit           = 1
            eofbit           = 2
            failbit          = 4

            oss.rdstate()    = 0
            oss.exceptions() = 0

executing:  oss.setstate(ios::badbit | ios::failbit);
            oss.rdstate()    = 5
            oss.exceptions() = 0

executing:  oss.exceptions(ios::failbit);

**** EXCEPTION THROWN ****
./a.out:  basic_ios::clear: iostream error
            oss.rdstate()    = 5
            oss.exceptions() = 4

所以根据 cplusplus.com 文档,我根本没想到会抛出异常。从异常处理程序中生成的输出可以看出,没有任何状态标志被清除。这是编译器错误、文档错误,还是我遗漏了什么?

顺便说一句,与记录的行为相比,我更喜欢展示的行为。对我来说,抛出错误的请求会产生消除现有错误的副作用,这对我来说似乎有点奇怪。实际上,我首先以与 g++ 显然相同的方式实现它(假设这是它肯定会工作的方式),然后才阅读该方法的文档。

cplusplus.com 是错误的。 clearexceptions 调用是正确的,但调用 not 来清除状态并且状态是 not 清除。

尽管名称如此,但 iostreams including setstate itself 在后端使用 clear 来完成流的大量设置的繁重工作,而不仅仅是清除状态。因此,它是容纳引发异常和其他与标志相关的行为的合乎逻辑的地方。

exceptions 中,似乎 clear 主要用于测试现有标志,以便在已设置任何所需标志的情况下引发异常。要在异常后真正清除标志,仍然需要调用 clear 来删除错误标志。