RAII获取破坏期间捕获的错误的方法

And*_*ndy 5 c++ error-handling destructor raii stack-unwinding

在维基百科上的文件I/O的RAII的典型示例中,吞下关闭文件时发生的任何错误:

#include <iostream>
#include <string> 
#include <fstream>
#include <stdexcept>

void write_to_file (const std::string & message) {
    // try to open file
    std::ofstream file("example.txt");
    if (!file.is_open())
        throw std::runtime_error("unable to open file");

    // write message to file
    file << message << std::endl;

    // file will be closed when leaving scope (regardless of exception)
}
Run Code Online (Sandbox Code Playgroud)

似乎没有办法确定file自动关闭时是否发生错误; 显然一个只能调用file.rdstate()file上的范围.

我可以file.close()手动调用然后检查错误,但是我必须在从示波器返回的每个地方都这样做,这违背了RAII的目的.

有些人评论说,在析构函数中只能发生文件系统损坏等不可恢复的错误,但我不相信这是正确的,因为析构函数AFAIK在关闭文件之前会刷新文件,并且在刷新时可能会发生可恢复的错误.

那么是否有一种常见的RAII方法来获取破坏期间发生的错误?我读到从析构函数中抛出异常是危险的,这听起来不像正确的方法.

我能想到的最简单的方法是注册一个回调函数,如果在破坏期间发生任何错误,析构函数将调用该函数.令人惊讶的是,似乎没有一个事件得到支持ios_base::register_callback.这似乎是一个重大的疏忽,除非我误解了一些事情.

但也许回调是在现代课程设计中被破坏时通知错误的最常见方式?

我假设在析构函数中调用任意函数也很危险,但是将调用包装在一个try/catch块中是完全安全的.

Jar*_*d42 4

您可以部分处理析构函数中的失败情况:

class Foo {
public:
    Foo() : count(std::uncaught_exceptions()) {}
    ~Foo() noexcept(false)
    {
        if (std::uncaught_exceptions() != count) {
            // ~Foo() called during stack unwinding
            // Cannot throw exception safely.
        } else {
            // ~Foo() called normally
            // Can throw exception
        }
    }
private:
    int count;
};
Run Code Online (Sandbox Code Playgroud)