LWG2349会有什么影响?

时间:2016-01-29 16:01:34

标签: c++ exception istream libstdc++ libc++

虽然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抛出任何错误?

1 个答案:

答案 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