考虑以下示例:
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)
这里我抛出一个类的对象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;
}
}
Run Code Online (Sandbox Code Playgroud)
我想这std :: current_exception()将使用某种类似的方式来访问异常,制作异常的副本,并实例化一个std :: exception_ptr可以稍后重新抛出的适当的异常。
那么我错过了什么吗?我尝试了一些微不足道的事情catch(auto x),但它似乎没有完成这项工作。
之前std::exception_ptr曾boost::exception_ptr尝试在没有直接语言支持的情况下实现此功能,因此需要更多样板代码才能工作。throw 使用 Boost,您必须在with处包装异常boost::enable_current_exception并抛出包装器。我实际上没有研究实现,但我想象包装器的复制构造函数设置一个线程本地指针指向自身(throw必须复制其参数),boost::current_exception然后检索(可能首先将异常复制到自由存储,以便它可以超越块catch)。为了catch (T x)仍然工作,包装器必须通过继承来包装原始异常,这使得它无法与原始类型一起使用。
另一种方法是复制原始数据,将线程本地指针设置为指向副本并抛出原始数据。这种方式适用于任何可抛出类型,但current_exception会引用与初始化catch参数所使用的实例不同的实例。
现在std::exception_ptr有直接的语言支持,不必跳过麻烦或进行过多的复制来存档它,但基本思想是相同的:将异常存储在类型擦除的容器中,该容器可以在抛出点重新抛出它并指向该异常。
| 归档时间: |
|
| 查看次数: |
3466 次 |
| 最近记录: |