考虑以下使用 boost 异常类的代码:
class exception : virtual public boost::exception {
// ...
};
template<typename Exc>
class exception_impl : virtual public std::exception
, public Exc {
public:
exception_impl(const Exc& exc) : Exc(exc) {}
virtual const char* what() const throw() {return "blah";}
};
(实际上,这段代码更复杂。例如,exception_impl
仅派生于std::exception
后者还不是 . 的直接或间接基类Exc
。但这只会分散我对问题的注意力,所以我跳过了它。)
鉴于此,我现在可以派生自己的异常类:
class some_exception : public exception {
// ...
};
并使用它们:
struct tag_test_int;
typedef boost::error_info<tag_test_int,int> test_int_info;
void f()
{
boost::throw_exception( exception_impl<some_exception>() << test_int_info(42) );
}
然而,事实证明,产生的异常没有test_int_info
对象。所以我更改了exception_impl
构造函数以提供一些诊断信息:
exception_impl(const Exc& exc)
: Exc(exc) {
std::cerr << "========================================================================\nexc:\n";
std::cerr << boost::diagnostic_information(exc);
std::cerr << "========================================================================\n*this:\n";
std::cerr << boost::diagnostic_information(*this);
std::cerr << "========================================================================\n";
}
这确实表明,当我将Exc
对象复制到exception_impl
基类对象中时,信息会丢失:
==================================================== ======================= 除: 抛出位置未知(考虑使用 BOOST_THROW_EXCEPTION) 动态异常类型:some_exception [tag_test_int*] = 42 ==================================================== ======================= *这: 抛出位置未知(考虑使用 BOOST_THROW_EXCEPTION) 动态异常类型:exception_impl 标准::异常::什么:“废话”
IIRC,异常对象必须根据标准是可复制的,并且忽略可能的优化,复制抛出表达式的结果。所以 boost 的异常必须是可复制的,并且它们当然不会在此过程中丢失信息。我必须在这里遗漏一些相当明显的东西。
我究竟做错了什么?