我不确定如何根据标准使用std::istream::exception
,如果无法将输入读入变量,则让std::istream::operator>>
抛出异常,例如双。
以下代码与clang / libc ++和gcc / libstdc ++具有不同的行为:
#include <iostream>
#include <cassert>
int main () {
double foo,bar;
std::istream& is = std::cin;
is.exceptions(std::istream::failbit);
is >> foo; //throws exception as expected with gcc/libstdc++ with input "ASD"
std::cout << foo;
is >> bar;
std::cout << bar;
assert(is); //failed with clang/libc++ after input "ASD"
std::cout << foo << " " << bar << std::endl;
}
根据C ++标准,is.exceptions(std::istream::failbit);
是否适合让operator>>
扔掉?
答案 0 :(得分:7)
首先是一些背景信息(如果您想进一步阐述,每个背景信息将在下面的相应标题下解释):
istream
ios_base::badbit
时,该标准要求basic_istream::exceptions
仅重新提交
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
上发生每个输入操作后{1}}。这需要看起来像这样:
istream
As noted by cpplearner你甚至无法使用basic_istream::fail
,你必须对if((is.rdstate() & ios_base::failbit) != 0) throw ios_base::failure("basic_ios::clear");
的{{3}}回复进行逐步测试。但老实说,这只会增加一些复杂性。
使这成为一项重大任务的原因是istream
的使用程度。 istream
的广泛使用可以通过辅助函数来解决,但是使用istream
s或提取运算符的复合重载会使人工检查这一任务变得不合理。
如果您发现自己在那里,我会认真考虑istream_iterator
解决方法的可能性。
is.exceptions(ios_base::failbit | ios_base::badbit)
istream
时,标准要求ios_base::badbit
仅重新提交
调用basic_istream::exceptions
将设置一个掩码,可以通过调用basic_istream::exceptions(istream::failbit)
来检索该掩码,根据标准的27.5.5.4 [iosstate.flags] / 11:
确定
basic_istream::exceptions()
中设置的元素会导致抛出异常的掩码。
对于未格式化的插入方法,27.7.2.2.3 [istream :: extractors] / 15支持此功能:
如果它没有插入任何字符,因为它在
rdstate()
中提取了*this
和failbit
中的字符时捕获了异常,那么捕获的异常就会被重新抛出。
但是对于格式化输入,这将在27.7.2.2.1 [istream.formatted.reqmts] / 1中进行逆行;只有在按位且掩码和exceptions()
非零时才要求抛出:
如果在输入过程中抛出异常,则会在
ios_base::badbit
的错误状态中打开ios::badbit
。如果*this
则重新抛出异常。
(exceptions()&badbit) != 0
应设置在相应ios_base::failbit
的事件上,例如:
istream
的数字,指针和布尔输入重载(技术上,它们调用的basic_istream::operator>>
的重载),如果输入无法解析为有效值或者解析的值不适合目的地类型。
[rdstate
]
如果仅在num_get::get
'掩码上设置了ios_base::failbit
并且发生了事件,则导致设置basic_istream::exceptions
,例如如上所述提取无效数字:
这个问题有一个no such exception is thrown。引用27.7.2.1 [istream] / 4
如果其中一个被调用的函数抛出异常,则除非另有明确说明,否则输入函数会将
ios_base::failbit
设置为错误状态。如果badbit
中有badbit
,则输入函数会重新抛出异常而不完成其操作,否则它不会抛出任何内容并继续进行,就像被调用函数返回了失败指示一样。
exceptions()
逐位提供ios_base::badbit
作为解决方法我们自己的now invalidated bug against libc++(也恰好是libc ++的代表,它使链接的libc ++ bug失效)Howard Hinnant(以及libc ++ bug)你使用了解决方法:
ios_base::iostate
答案 1 :(得分:2)
似乎libc ++遵循这个要求:
每个格式化的输入函数通过使用
sentry
构造类noskipws
的对象来开始执行 (第二)论证false
。如果sentry对象返回true
,则转换为类型bool
的值时, 函数努力获得所请求的输入。 如果在输入过程中抛出异常,则ios::badbit
在*this
的错误状态下打开 312 。如果(exceptions()&badbit) != 0
则重新抛出异常。 在任何情况下,格式化的输入功能都会破坏哨兵对象。如果没有抛出异常,那就是 返回*this
。312)这样做不会导致
ios::failure
被抛出。
(引自N4567§27.7.2.2.1[istream.formatted.reqmts],但C ++ IS包含相同的措辞。强调我的)
我不知道这是否真的意味着“if (exceptions()&badbit) == 0
然后输入函数不会抛出任何异常”,不过。