Giới thiệu:C++ suy ra kiểu của một ngoại lệ lồng nhau
đưa ra:
struct X : std::runtime_error {
using std::runtime_error::runtime_error;
};
Khi chúng ta gọi là std::throw_with_nested(X("foo"))
, những gì đang thực sự ném không phải là một X
. Đó là một số loại có nguồn gốc từ cả hai số X
và std::nested_exception
.
do đó, sự khẳng định sau sẽ thất bại:
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()));
Những gì tôi muốn làm là suy luận rằng hai trường hợp ngoại lệ này có liên quan.
nỗ lực đầu tiên:
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);
}
}
này sai vì std::nested_exception::nested_ptr()
trả về một con trỏ đến ngoại trừ tiếp theo xuống dòng, không phải là giao diện X
của ngoại lệ hiện hành.
Tôi đang tìm ý tưởng và giải pháp (di động) cho phép tôi khôi phục typeid (X) từ 'ngoại lệ với tên không xác định' được thư viện chuẩn ném trong thời gian std::rethrow_exception
.
C++ 14 và C++ 1z là tốt.
Tại sao ?:
Bởi vì tôi muốn để có thể unwrap một hệ thống phân cấp ngoại lệ hoàn thành và chuyển nó qua một phiên rpc, hoàn chỉnh với tên loại ngoại lệ.
Tôi lý tưởng không muốn phải viết một khối catch có tất cả các loại ngoại lệ trong hệ thống, mà sẽ phải được đặt hàng yếu bởi độ sâu dẫn xuất.
Một ví dụ khác của chức năng dự kiến (và minh họa về lý do tại sao cách tiếp cận của tôi không hoạt động):
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 ghi nhận, cảm ơn. Như bạn có thể thấy, tôi đang sử dụng type_index trong mã. Tôi sẽ cập nhật câu hỏi để so sánh a và b theo tên(). –
Lưu ý chắc chắn những gì bạn muốn chứng minh với ví dụ cuối cùng của bạn, bạn có 'std :: runtime_error' vs' X' ... – Jarod42
@ Jarod42 đúng. X là gói một runtime_error lồng nhau. Tôi muốn suy ra loại X (trình bao bọc) từ loại thực của nó. –