LWG2349会有什么影响?

Jon*_*Mee 7 c++ exception istream libstdc++ libc++

虽然libstdc ++没有,但libc ++确实遵循标准,该标准规定传递ios_base::failbitbasic_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抛出任何错误?

eca*_*mur 7

除例外"的语言点从抛出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)

  • @JonathanMee有助于了解例如27.7.2.1 [istream]/4:"如果其中一个被调用的函数抛出异常,那么除非另有明确说明,否则输入函数会将badbit设置为错误状态.如果badbit在异常中打开(),输入函数重新抛出异常而不完成其动作,否则它不会抛出任何东西并继续进行,就像被调用的函数返回了失败指示一样." LWG2349的目的是确保来自其他用户代码(不仅仅是`sbumpc`和`sgetc`)的用户抛出的异常行为类似. (2认同)