std::current_exception 是如何工作的?

Mat*_*nti 5 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里我抛出一个类的对象myclassstd :: 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 中的某种原语吗?例如,decltype或者sizeof?或者还有另一种方法来访问隐藏在其中的异常吗catch(...)

例如,有没有办法只打印出异常,无论它是什么?就像是:

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

我想这std :: current_exception()将使用某种类似的方式来访问异常,制作异常的副本,并实例化一个std :: exception_ptr可以稍后重新抛出的适当的异常。

那么我错过了什么吗?我尝试了一些微不足道的事情catch(auto x),但它似乎没有完成这项工作。

yur*_*hek 2

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

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

现在std::exception_ptr有直接的语言支持,不必跳过麻烦或进行过多的复制来存档它,但基本思想是相同的:将异常存储在类型擦除的容器中,该容器可以在抛出点重新抛出它并指向该异常。