Jon*_*Mee 7 c++ exception istream libstdc++ libc++
虽然libstdc ++没有,但libc ++确实遵循标准,该标准规定传递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";
}
Run Code Online (Sandbox Code Playgroud)
会导致:
我对LWG2349的阅读是因为它basic_istream不会抛出任何格式化的输入.
例如,LWG2349建议对标准的27.7.2.3 [istream]/1进行更改,该标准引用了一个错误的失效,该错误会使libc ++行为像libstdc ++.更改以粗体显示,并在下面进行说明:
如果在输入期间抛出除抛出的异常
clear()(如果有的话)之外的异常,则ios::badbit在*this错误状态下打开.(抛出的异常如果basic_ios<>::clear()不会被捕获或重新抛出.)(exceptions()&badbit) != 0那么异常被重新抛出.
我明白这basic_istream::clear是对错误的格式化输入的反应,所以我误读了LWG2349还是实际上它会停止basic_istream抛出任何错误?
除例外"的语言点从抛出clear() "是保证如果 clear()抛出,因为输入功能已经呼吁clear(failbit) 和 (exceptions() & failbit) != 0,然后badbit没有被设置为一个结果.clear()在这种情况下会继续抛出,它只是不会设置badbit.
如LWG2349的评论中所述,目的是在从用户代码抛出异常时设置badbit:
PJ和Matt都同意(badbit + rethrow)的意图是"表示用户代码中出现的异常,而不是iostreams包".
现在,什么时候可以通过"用户代码"抛出异常但是在iostreams机器中?一个例子是locale getters:
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';
}
Run Code Online (Sandbox Code Playgroud)
目前,gcc输出:
eof fail
Run Code Online (Sandbox Code Playgroud)
clang输出:
eof fail
Run Code Online (Sandbox Code Playgroud)
在LWG2349之后,正确的行为是设置badbit并重新抛出异常:
my_get::do_get
eof bad
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1552 次 |
| 最近记录: |