【发布时间】:2016-05-16 14:30:19
【问题描述】:
简介:
给定:
struct X : std::runtime_error {
using std::runtime_error::runtime_error;
};
当我们调用std::throw_with_nested(X("foo")) 时,实际抛出的不是X。它是从X 和std::nested_exception 派生的某种类型。
因此,以下断言将失败:
const std::type_info *a = nullptr, *b = nullptr;
try
{
throw X("1");
}
catch(X& x) {
a = std::addressof(typeid(x));
try {
std::throw_with_nested(X("2"));
}
catch(X& x) {
b = std::addressof(typeid(x));
}
}
assert(std::string(a->name()) == std::string(b->name()));
我想做的是推断这两个异常是相关的。
第一次尝试:
std::type_index
deduce_exception_type(const std::exception* pe)
{
if (auto pnested = dynamic_cast<const std::nested_exception*>(pe))
{
try {
std::rethrow_exception(pnested->nested_ptr());
}
catch(const std::exception& e)
{
return deduce_exception_type(std::addressof(e));
}
}
else {
return typeid(*pe);
}
}
这会失败,因为std::nested_exception::nested_ptr() 返回指向下一个异常的指针,而不是当前异常的X 接口。
我正在寻找(便携式)想法和解决方案,使我能够从std::rethrow_exception 期间标准库抛出的“未知名称的异常”中恢复 typeid(X)。
c++14 和 c++1z 都可以。
为什么?:
因为我希望能够解开完整的异常层次结构并通过 rpc 会话传输它,并带有异常类型名称。
理想情况下,我不想编写一个包含系统中每种异常类型的 catch 块,这必须按派生深度进行弱排序。
预期功能的进一步示例(以及我的方法不起作用的说明):
const std::type_info *b = nullptr;
try
{
throw std::runtime_error("1");
}
catch(std::exception&) {
try {
std::throw_with_nested(X("2"));
}
catch(X& x) {
// PROBLEM HERE <<== X& catches a std::_1::__nested<X>, which
// is derived from X and std::nested_exception
b = std::addressof(typeid(x));
}
}
assert(std::string(typeid(X).name()) == std::string(b->name()));
【问题讨论】:
-
@Jarod42 指出,谢谢。如您所见,我在代码中使用了 type_index。我将更新问题以按名称()比较 a 和 b。
-
注意你想用最后一个例子演示什么,你有
std::runtime_errorvsX... -
@Jarod42 没错。 X 包装了一个嵌套的 runtime_error。我想从未命名的真实类型中推断出 X(包装器)的类型。
-
@Jarod42 好的,很抱歉。我已经修正了错字。
标签: c++ c++11 exception c++14 c++17