虽然libstdc ++没有,但libc ++确实遵循the standard which states,将ios_base::failbit
传递给basic_istream::exceptions
对格式化输入没有影响。例如这段代码:
istringstream is{"ASD"};
double foo;
is.exceptions(istream::failbit);
try {
is >> foo;
cout << foo << endl;
} catch(ios_base::failure& fail) {
cout << "ouch\n";
}
会导致:
我对LWG2349的解读是,它会导致basic_istream
不抛出任何格式化的输入。
例如,LWG2349建议更改标准的27.7.2.3 [istream] / 1,引用the invalidation of a bug that would have made libc++ behave like libstdc++引用。更改以粗体显示,并在下面进行说明:
如果在输入过程中抛出异常,而不是从
clear()
抛出的异常 ,则会在ios::badbit
中启用*this
错误状态。(从如果basic_ios<>::clear()
抛出的异常不被捕获或重新抛出。)(exceptions()&badbit) != 0
则重新抛出异常。
I understand that basic_istream::clear
is what throws in reaction to bad formatted input所以我误读LWG2349还是实际上是要阻止basic_istream
抛出任何错误?
答案 0 :(得分:5)
排除异常“从clear()
抛出”的语言的要点是确保 if clear()
抛出,因为输入函数有称为clear(failbit)
和 (exceptions() & failbit) != 0
,然后不会将badbit设置为结果。 <{1}}将继续抛出这种情况,它不会设置badbit。
如LWG2349的评论所述,目的是在用户代码抛出异常时设置badbit:
PJ和Matt都同意(badbit + rethrow)的意图是“表示用户代码中出现的异常,而不是iostreams包”。
现在,什么时候可以通过“用户代码”抛出异常但是在iostreams机器中?一个例子是locale getters:
clear()
目前,gcc输出:
struct my_get : std::num_get<char> {
using iter_type = std::istreambuf_iterator<char>;
iter_type do_get(iter_type, iter_type, std::ios_base&, std::ios_base::iostate&, bool&) const override {
throw std::logic_error{"my_get::do_get"};
}
};
int main() {
std::istringstream iss;
iss.imbue({std::locale{}, new my_get});
iss.exceptions(std::ios_base::failbit | std::ios_base::badbit);
try {
bool b;
iss >> b;
} catch (std::exception& ex) {
std::cout << ex.what() << '\n';
}
std::cout
<< ((iss.rdstate() & std::ios_base::eofbit) ? "eof " : "")
<< ((iss.rdstate() & std::ios_base::failbit) ? "fail " : "")
<< ((iss.rdstate() & std::ios_base::badbit) ? "bad " : "")
<< '\n';
}
clang输出:
eof fail
在LWG2349之后,正确的行为是设置badbit并重新抛出异常:
eof fail