如何使用std :: nested_exception和朋友?

Omn*_*ous 27 c++ exception-handling

我注意到<exception>在C++ 11 中有一些更有趣的声明.任何人都可以阐明它们的含义以及如何使用它们吗?

我想知道的是:

  1. ::std::nested_exception
  2. ::std::throw_with_nested
  3. ::std::rethrow_if_nested

此外,虽然它们看起来不言自明,但了解它们如何工作可能会很好:

  1. ::std::exception_ptr
  2. ::std::make_exception_ptr
  3. ::std::current_exception
  4. ::std::rethrow_exception

ybu*_*ill 24

一些高级代码通常会捕获std::exception并打印出来what().您希望尽可能多地将信息压缩到此通用机制,同时不丢失任何信息.考虑一些归档库的实现:

archive::archive(const char* filename)
{
    ifstream file(filename)
    file.exceptions(ios_base::badbit);
    open_archive(file); // throws ios_base::failure, or some other low-level exception.
}
Run Code Online (Sandbox Code Playgroud)

不记录存档可用的信息(例如文件名).此外,您希望区分来自归档类的异常与其他异常.

archive::archive(const char* filename)
{
    try {
        ifstream file(filename)
        file.exceptions(ios_base::badbit);
        open_archive(file); // throws ios_base::failure, or some other low-level exception.
    } catch(const std::exception& e) {
        throw archive_exception("Can't open archive", filename, e.what());
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们添加了archive类知道的更高级别的语义信息,但是我们也丢失了有关问题的原始原因(类型e)的信息.nested_exception意在解决这个问题:

archive::archive(const char* filename)
{
    try {
        ifstream file(filename)
        file.exceptions(ios_base::badbit);
        open_archive(file); // throws ios_base::failure, or some other low-level exception.
    } catch(...) {
        throw_with_nested(archive_exception("Can't open archive", filename));
    }
}
Run Code Online (Sandbox Code Playgroud)

记录所有可用信息.我们现在可以在catch站点中一般地检索它:

void print_exception_info(const std::exception& e)
{
    cerr << e.what() << "\n";
    try {
        rethrow_if_nested(e);
    } catch(const std::exception& ne) {
        print_exception_info(ne);
    } catch(...) { }
}

int main() {
    try {
        run();
    } catch(const std::exception& e) {
        print_exception_info(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出将比以前更具描述性.它将描述从高级到低级的问题:

无法打开存档"my_archive.bin"

访问被拒绝.

也许:

无法打开存档"my_archive.bin"

记录'aabb'未找到.

使用的函数exception_ptr旨在在线程之间传输异常,或者更一般地,存储异常以供以后使用.它们如何工作取决于实施.意图是exception_ptr将成为异常对象的共享指针.但是,当创建此指针时,抛出异常或尝试获取异常时exception_ptr,将受到实现的约束.调用时,实现仍然可以自由复制异常current_exception().