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

时间:2017-08-04 03:21:37

标签: c++ c++11

假设我有./script.sh: line 5: syntax error near unexpected token `$'{\r'' '/script.sh: line 5: `foo(){ 个实例。我需要检查底层异常是否属于某种类型(理想情况下可以访问它)。它可以这样做:

std::exception_ptr

有更好的方法吗?

是否有保证std::exception_ptr p = ...; try { std::rethrow_exception(p); } catch(MyType const& x) { ... } catch(...) { // do smth else } 无法复制基础异常,从而导致抛出std::rethrow_exception等问题?

1 个答案:

答案 0 :(得分:0)

std::rethrow_exception是检索底层异常对象的唯一方法,因此必须使用它。假设每个例外都是从std::exception继承而来的,那么你就可以做出动态广播' 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);
        }
    }
}