尽管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";
}
将导致:
  • "ouch" on libstdc++
  • "0" on libc++

  • 我对LWG2349的阅读是,它将导致basic_istream不会抛出任何格式化的输入。
    例如,LWG2349提出了对标准27.7.2.3 [istream]/1的更改,该更改引用了the invalidation of a bug that would have made libc++ behave like libstdc++引用。更改以粗体显示,并删除如下:

    I understand that basic_istream::clear is what throws in reaction to bad formatted input,所以我会误读LWG2349还是实际上会阻止basic_istream抛出任何错误?

    最佳答案

    该语言排除“从clear()中抛出”异常的目的是为了确保,如果clear()抛出,因为输入函数调用了clear(failbit)(exceptions() & failbit) != 0,则不会设置badbit。在这种情况下,clear()将继续抛出,只是不会设置badbit。

    如LWG2349的注释中所述,其目的是当从用户代码引发异常时设置badbit:



    现在,什么时候可以在iostreams机制中通过“用户代码”引发异常?一个示例是区域设置获取程序:

    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';
    }
    

    目前,gcc输出:
    eof fail
    

    lang输出
    eof fail
    

    在LWG2349之后,正确的行为是设置badbit并重新抛出异常:
    my_get::do_get
    eof bad
    

    08-28 21:02