考虑以下示例:
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中是某种原始的吗?例如,decltype
或sizeof
?或者是否有其他方法可以访问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)
这样的小事,但它似乎没有做到这一点。
答案 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
有直接语言支持,不需要跳过箍或过度复制来存档,但基本思路是这样的:将异常存储在可以重新抛出它的类型擦除容器中抛出点并指向它。