当我使用boost::copy_exception
将异常复制到exception_ptr
,我丢失了类型信息。看一下下面的代码:
try {
throw std::runtime_error("something");
} catch (exception& e) {
ptr = boost::copy_exception(e);
}
if (ptr) {
try {
boost::rethrow_exception(ptr);
} catch (std::exception& e) {
cout << e.what() << endl;
cout << boost::diagnostic_information(e) << endl;
}
}
由此,我得到以下输出:
N5boost16exception_detail10clone_implISt9exceptionEE
Dynamic exception type: boost::exception_detail::clone_impl<std::exception>
std::exception::what: N5boost16exception_detail10clone_implISt9exceptionEE
所以基本上boost::copy_exception
静态复制它得到的参数。
如果我抛出异常,这个问题就可以解决boost::enable_current_exception
相反,像这样。
try {
throw boost::enable_current_exception(std::runtime_error("something"));
} catch (...) {
ptr = boost::current_exception();
}
if (ptr) {
try {
boost::rethrow_exception(ptr);
} catch (std::exception& e) {
cout << e.what() << endl;
cout << boost::diagnostic_information(e) << endl;
}
}
这样做的问题是,有时异常是由不使用的库引发的boost::enable_current_exception
。在这种情况下,有什么办法可以将异常放入exception_ptr
除了一一捕获每种可能的异常并使用boost::copy_exception
每一个?
这是设计使然,您的分析是正确的:使用静态类型,而不是动态类型。事实上,为了避免这种意外,boost::copy_exception
became std::make_exception_ptr
在导致 C++11 的过程中。这样一来,就更清楚了current_exception
(无论是 Boost 版本还是 C++11 版本)是正确捕获当前异常的正确方法。我强烈推荐使用BOOST_THROW_EXCEPTION
, 或者至少boost::throw_exception
,当涉及到在代码中使用支持 Boost.Exception 的异常时。
当涉及第三方代码时,除了您已经提到的解决方案或其他一些道德等价物(例如dynamic_cast
- 构成异常类型层次结构的不同叶类,或者typeid
abuse).
在这方面,异常处理与处理一个或多个多态类型层次结构相同,并且在这种情况下您尝试的操作是虚拟副本,也称为克隆:或者您的代码被侵入性地设计为支持该操作(如使用例如时就是这种情况BOOST_THROW_EXCEPTION(e);
代替throw e;
),否则你将痛苦地走过继承树。请注意,您至少可以将这种痛苦重构为一个站点,这样您最终会得到例如
try {
third_party_api();
} catch(...) {
ptr = catch_exceptions_from_api();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)