std :: current_exception如何工作?

时间:2017-07-09 16:04:59

标签: c++ exception

考虑以下示例:

class myclass
{
public:

    void f() const
    {
        std :: cout << "Hello from myclass!" << std :: endl;
    }
};

int main()
{
    std :: exception_ptr x;

    try
    {
        throw myclass();
    }
    catch(...)
    {
        x = std :: current_exception();
    }

    try
    {
        std :: rethrow_exception(x);
    }
    catch(const myclass & n)
    {
        n.f();
    }
}

在这里,我抛出一个类myclass的对象,并在std :: current_exception()块中使用catch(...)来获得std :: exception_ptr。之后我使用std :: rethrow_exception来再次抛出异常并抓住它,这次是catch(const myclass &),这样我就可以打电话给f()并打印Hello from myclass!

现在。我想象一下如何实现类似于std :: exception_ptr的东西:一个指向基类的指针,每个可能类型的模板包装器都从该指针继承,还有一些允许再次抛出的rethrow虚拟方法例外。到目前为止一切都很好。

现在,std :: current_exception()如何运作?它是如何实现的?我尝试使用我的Xcode检查它,但我有一个很好的闪烁问号:?。这在C ++ 11中是某种原始的吗?例如,decltypesizeof?或者是否有其他方法可以访问catch(...)中隐藏的异常?

例如,有没有办法打印出异常,无论它是什么?类似的东西:

template <typename type> void printme(const type & exception)
{
    try
    {
        throw exception;
    }
    catch(...)
    {
        std :: cout << /* SOME MAGIC HERE */ << std :: endl;
    }
}

我想std :: current_exception()将使用一些类似的方式来访问异常,复制它,并实例化一个可以在以后重新抛出的适当的std :: exception_ptr

所以我错过了什么?我尝试了一些像catch(auto x)这样的小事,但它似乎没有做到这一点。

1 个答案:

答案 0 :(得分:1)

std::exception_ptr之前,有boost::exception_ptr试图在没有直接语言支持的情况下实现此功能,因此需要更多的样板代码才能工作。使用Boost,您必须使用boost::enable_current_exception将异常包装在throw处,然后抛出包装器。我实际上没有研究过实现,但我想包装器的复制构造函数设置一个指向自身的线程局部指针(throw必须复制它的参数)boost::current_exception然后检索(可能复制异常)首先释放商店,以便它可以比catch块更长久。要使catch (T x)仍然有效,包装器必须通过继承它来包装原始异常,这使得它无法与原始类型一起使用。

另一种方法是复制原件,将线程局部指针设置为指向副本并抛出原件。这种方式适用于任何可抛出类型,但current_exception将引用与初始化catch参数所使用的实例不同的实例。

现在std::exception_ptr有直接语言支持,不需要跳过箍或过度复制来存档,但基本思路是这样的:将异常存储在可以重新抛出它的类型擦除容器中抛出点并指向它。