我正在编写自己的输出流库,我试图模仿std :: ostream行为,它不会与我想要实现的新行为发生冲突。目前我正在尝试模仿从ios继承的这个接口:
std::ostream::exceptions(ios::iostate state)
“此方法为流设置一个新的异常掩码,并清除流的错误状态标志(就像调用成员clear()一样)。”
我不清楚这是否意味着所有标志都将被清除或只是在异常掩码中设置的那些,所以我写了一个测试程序,但得到了意想不到的结果。这是程序:
#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错了。 clear
调用exceptions
是正确的,但是没有调用它来清除状态并且状态没有被清除。
尽管有这个名字,clear
在后端被iostreams including setstate
itself用来做大量的设置,而不仅仅是清除流的状态。因此,它是提出异常和其他与旗帜相关的行为的合理场所。
在exceptions
中,如果已经设置了任何所需的标志,则clear
主要用于测试现有标志以引发异常。要在异常后实际清除标志,仍然需要调用clear
来删除错误标志。