Introduzione:C++ dedurre il tipo di un'eccezione annidata
dato:
struct X : std::runtime_error {
using std::runtime_error::runtime_error;
};
Quando chiamiamo std::throw_with_nested(X("foo"))
, ciò che è effettivamente gettato non è un X
. È un tipo derivato sia da X
sia da std::nested_exception
.
quindi, la seguente asserzione avrà esito negativo:
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()));
Quello che vorrei fare è dedurre che queste due eccezioni riguardano.
Primo tentativo:
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);
}
}
Questo fallisce perché std::nested_exception::nested_ptr()
restituisce un puntatore alla prossima eccezione verso il basso la linea, non l'interfaccia X
dell'eccezione corrente.
Sto cercando idee e soluzioni (portatili) che mi consentano di recuperare il tipoid (X) dall''eccezione con nome sconosciuto 'generata dalla libreria standard durante std::rethrow_exception
.
C++ 14 e C++ 1z vanno bene.
Perché ?:
Perché voglio essere in grado di scartare una gerarchia un'eccezione completo e trasmetterlo attraverso una sessione RPC, con nomi tipo di eccezione.
Preferibilmente non voglio dover scrivere un blocco catch con ogni tipo di eccezione nel sistema, che dovrebbe essere debolmente ordinato per profondità di derivazione.
Un ulteriore esempio di funzionalità prevista (e un'illustrazione del motivo per cui il mio approccio non funziona):
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 notato, grazie. Come puoi vedere, sto usando type_index nel codice. Aggiornerò la domanda per confrontare aeb per nome(). –
Nota che cosa vuoi dimostrare con il tuo ultimo esempio, hai 'std :: runtime_error' vs' X' ... – Jarod42
@ Jarod42 giusto. X sta eseguendo il wrapping di un runtime_error nidificato. Voglio dedurre il tipo di X (il wrapper) dal suo tipo reale non nominato. –