首先是一些背景信息(如果您想进一步阐述,每一个都在其各自的标题下解释):
- 标准要求
istreams 仅在ios_base::badbit 设置为basic_istream::exceptions 时重新抛出
- libstdc++ 不符合此要求,但 libc++ 符合
- libc++ 使请求它镜像 libstdc++ 行为的错误无效
- libc++ 提供
ios_base::badbit 与所需的ios_base::iostate 按位或作为解决方法
不幸的是,这种解决方法的副作用是每当 ios_base::badbit 设置为独立于 ios_base::failbit 时也会重新抛出:http://en.cppreference.com/w/cpp/io/ios_base/iostate#The_badbit
如果您希望仅在设置ios_base::failbit 时发生抛出,并且您需要它在 libc++ 和 libstdc++ 上具有相同的行为,则必须检查 ios_base::badbit在istream 上发生的每个输入操作之后。这需要看起来像这样:
if((is.rdstate() & ios_base::failbit) != 0) throw ios_base::failure("basic_ios::clear");
As noted by cpplearner 你甚至不能使用basic_istream::fail,你必须对istream 的rdstate 返回进行逐位测试。但老实说,这只会增加一点复杂性。
使这项任务成为一项艰巨任务的是istream 的使用程度。 istream 的广泛使用可以通过辅助函数来解决,但是使用 istream_iterators 或提取运算符的复合重载很快就会使手动检查这个任务变得不合理。
如果你发现自己在那里,我会认真考虑is.exceptions(ios_base::failbit | ios_base::badbit) 解决方法的可能性。
标准要求istreams 仅在ios_base::badbit 设置为basic_istream::exceptions 时重新抛出
调用basic_istream::exceptions(istream::failbit) 将设置一个掩码,该掩码可以通过调用basic_istream::exceptions() 来检索,根据标准的27.5.5.4 [iosstate.flags]/11 是:
确定rdstate() 中设置的哪些元素会引发异常的掩码。
27.7.2.2.3 [istream::extractors]/15 支持无格式插入方法:
如果由于在*this (27.5.5.4) 中从*this 和failbit 中提取字符时捕获到抛出的异常而未插入任何字符,则重新抛出捕获的异常。
但是,对于格式化输入,这将在 27.7.2.2.1 [istream.formatted.reqmts]/1 中回退;仅当掩码的位与和ios_base::badbit 不为零时才需要抛出:
如果在输入过程中抛出异常,则 ios::badbit 在 *this 的错误状态下打开。如果(exceptions()&badbit) != 0 则重新抛出异常。
libstdc++ 不符合此要求,但 libc++ 符合
ios_base::failbit 应设置在其各自的 istream 上,例如:
basic_istream::operator>> 的数字、指针和布尔输入重载(从技术上讲,他们调用 num_get::get 的重载),如果输入无法解析为有效值或解析的值不适合目标输入。
[Source]
如果在basic_istream::exceptions'掩码上只设置了ios_base::failbit,并且发生了一个事件,导致ios_base::failbit被设置,例如如上所述提取无效数字:
libc++ 使请求它镜像 libstdc++ 行为的错误无效
这个问题有一个now invalidated bug against libc++。引用 27.7.2.1 [istream]/4
如果这些被调用函数之一引发异常,则除非另有明确说明,否则输入函数会将badbit 设置为错误状态。如果badbit 在exceptions() 中打开,则输入函数会在未完成其操作的情况下重新抛出异常,否则它不会抛出任何东西并继续进行,就好像被调用的函数返回了失败指示一样。
libc++ 提供 ios_base::badbit 按位或所需的 ios_base::iostate 作为解决方法
我们自己的Howard Hinnant(他也恰好是使链接的 libc++ 错误无效的 libc++ 代表)suggests in answer to a duplicate of this question(以及在 libc++ 错误中),您使用了解决方法:
is.exceptions(ios_base::failbit | ios_base::badbit);