c++ - 是否可以检查给定的 exception_ptr 实例是否拥有某种类型的异常?

标签 c++ c++11

假设我有一个 std::exception_ptr 实例。我需要检查底层异常是否属于某种类型(理想情况下可以访问它)。可以这样做:

std::exception_ptr p = ...;
try
{
    std::rethrow_exception(p);
}
catch(MyType const& x)
{
    ...
}
catch(...)
{
    // do smth else
}

有没有更好的办法?

是否可以保证 std::rethrow_exception 不会复制导致抛出 std::bad_alloc 等问题的底层异常?

最佳答案

std::rethrow_exception 是检索底层异常对象的唯一方法,因此必须使用它。假设每个异常都继承自 std::exception,您可以创建“dynamic_cast”if-else 链。我已经用虚拟异常尝试过它并且它有效。如果更好-这是品味问题。在这种方法中,更容易拥有一些共享上下文或做两种情况或在两种类型的情况下做某事。

你的问题中更有趣的部分是关于复制对象——根据 C++ 引用 std::exception_ptr “是一个类似共享指针的类型”,所以不应该发生复制。虽然,我制作了简单的测试用例,它确实在 Visual Studio 2017 中被复制了。它在 GCC 中运行良好。我没有关于其他编译器的信息。

#include <cstdio>
#include <string>
#include <exception>

class A :public std::exception
{
public: 
};


class B :public std::exception
{
public:
    virtual const char* what() const
    {
        return "B";
    }
    B() { printf("Created B at %X\n", this); }
    B(const B& b) { printf("Copied B from %X at %X\n", &b, this); } // make it copyable
    B& operator=(const B& b) { printf("Copied B from %X at %X\n", &b, this); return *this;}; // make it copyable
    B(const B&& b) { printf("Moved B from %X at %X\n", &b, this); } // make it movable

};

class C : public B
{
public:
    int q;

    C(int qq) { q = qq; printf("Created C at %X with q=%d\n", this, q); }
    C(const C& c) :B(c) { q = c.q; printf("Copied C from %X at %X\n", &c, this); } // make it copyable
    C& operator=(const C& c) { q = c.q; printf("Copied C from %X at %X\n", &c, this); return *this; }; // make it copyable
    C(const C&& c):B(std::move(c)) { q = std::move(c.q); printf("Moved C from %X at %X\n", &c, this); } // make it movable
};

int main()
{
    // Check does rethrow_exception copies underlying object
    try
    {
        B b; // B created
        throw std::move(b);
    }
    catch (...)
    {
        auto p = std::current_exception();
        try
        {
            std::rethrow_exception(std::move(p));
        }
        catch (...)
        {
            auto p = std::current_exception();
            try
            {
                std::rethrow_exception(p);
            }
            catch (B& b) // refered to last copy
            {
                printf("done with B at %X\n", &b);
            }
        }
    }


    printf("\n");
    // Try with dynamic_cast
    try {
        C c(12);
        throw std::move(c);
    }
    catch (...)
    {
        printf("Caught something\n");
        auto p = std::current_exception();
        try {
            std::rethrow_exception(p);
        }
        catch (std::exception& ex)
        {
            printf("Caught ex\n");
            if (A* a = dynamic_cast<A*>(&ex))
                printf("ex is A\n");
            if (B* b = dynamic_cast<B*>(&ex))
                printf("ex is B\n");
            if (C* c = dynamic_cast<C*>(&ex))
                printf("ex is also C with q=%d\n", c->q);
        }
    }
}

关于c++ - 是否可以检查给定的 exception_ptr 实例是否拥有某种类型的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45497765/

相关文章:

c++ - 用作基类接口(interface)的一部分的 header 是否应该包含在派生类中

c++ - 为什么显式模板实例化会在存在外线虚拟时导致 weak-template-vtables 警告?

c++ - 具有连续存储的动态矩阵

c++ - 为什么 c++ 命名空间内的定义在命名空间外工作?

c++ - tink_core Future (haxe) 形式 c++

c++ - C++11 中无法识别的命令行

c++ - 析构函数中的 std::ios::exceptions 预期行为是什么?

c++ - 当两个 std::map 对象相同时

c++ - 使用仿函数或 lambda 的 vector 深度复制

c++ - 现代 CMake 应该如何添加 SSE 标志?