C’est le code que j’ai.
try { // code throws potentially unknown exception } catch (...) { std::exception_ptr eptr = std::current_exception(); // then what ? }
Idéalement, j’aimerais obtenir la chaîne associée à l’exception s’il s’agit d’un std :: exception.
Utiliser std::current_exception
semble un peu std::current_exception
dans votre cas, car vous ne semblez pas vouloir stocker ou copier std::exception_ptr
pour un traitement ultérieur (son seul but étant de ne pas vous aider à obtenir des informations supplémentaires. informations sur une exception inconnue de quelque manière que ce soit). Si vous voulez juste traiter le cas d’un std::exception
, qu’en est-il du simple:
try { // code throws potentially unknown exception } catch (const std::exception &e) { std::cerr << e.what() << '\n'; // or whatever } catch (...) { // well ok, still unknown what to do now, // but a std::exception_ptr doesn't help the situation either. std::cerr << "unknown exception\n"; }
try { std::rethrow_exception(eptr); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; }
// alors quoi?
voici quoi:
#include #include #include #include std::ssortingng what(const std::exception_ptr &eptr = std::current_exception()) { if (!eptr) { throw std::bad_exception(); } try { std::rethrow_exception(eptr); } catch (const std::exception &e) { return e.what() ; } catch (const std::ssortingng &e) { return e ; } catch (const char *e) { return e ; } catch (...) { return "who knows"; } } int main() { try { throw std::runtime_error("it's success!"); } catch (...) { std::cerr << "Here is WHAT happened: " << what() << std::endl; } try { throw 42; } catch (...) { std::cerr << "and now what: " << what() << std::endl; } }
ce qu'il imprime:
Here is WHAT happened: it's success! and now what: who knows
http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24
cela permet donc d’obtenir what
dans la clause fourre-tout.
mais que se passe-t-il si une exception est nestede ??? voici quoi:
std::ssortingng what(const std::exception_ptr &eptr = std::current_exception()); template std::ssortingng nested_what(const T &e) { try { std::rethrow_if_nested(e); } catch (...) { return " (" + what(std::current_exception()) + ")"; } return {}; } std::ssortingng what(const std::exception_ptr &eptr) { if (!eptr) { throw std::bad_exception(); } try { std::rethrow_exception(eptr); } catch (const std::exception &e) { return e.what() + nested_what(e); } catch (const std::ssortingng &e) { return e ; } catch (const char *e) { return e ; } catch (...) { return "who knows"; } }
en utilisant l'exemple d' ici :
#include ... // sample function that catches an exception and wraps it in a nested exception void open_file(const std::ssortingng& s) { try { std::ifstream file(s); file.exceptions(std::ios_base::failbit); } catch(...) { std::throw_with_nested( std::runtime_error("Couldn't open " + s) ); } } // sample function that catches an exception and wraps it in a nested exception void run() { try { open_file("nonexistent.file"); } catch(...) { std::throw_with_nested( std::runtime_error("run() failed") ); } } int main() { try { throw std::runtime_error("success!"); } catch (...) { std::cerr << "Here is WHAT happened: \"" << what() << '\"' << std::endl; } try { run(); } catch (...) { std::cerr << "what happened for run: \"" << what() << '\"' << std::endl; } }
ce qui est imprimé:
Here is WHAT happened: "success!" what happened for run: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))"
http://coliru.stacked-crooked.com/a/901a0c19297f02b5
mais que faire si la récursion est trop profonde? Et si stackoverflow? optimisé quoi:
#include template std::exception_ptr get_nested(const T &e) { try { auto &nested = dynamic_cast(e); return nested.nested_ptr(); } catch (const std::bad_cast &) { return nullptr; } } #if 0 // alternative get_nested std::exception_ptr get_nested() { try { throw ; } catch (const std::nested_exception &e) { return e.nested_ptr(); } catch (...) { return nullptr ; } } #endif std::ssortingng what(std::exception_ptr eptr = std::current_exception()) { if (!eptr) { throw std::bad_exception(); } std::ssortingng whaaat; std::size_t num_nested = 0; next: { try { std::exception_ptr yeptr; std::swap(eptr, yeptr); std::rethrow_exception(yeptr); } catch (const std::exception &e) { whaaat += e.what() ; eptr = get_nested(e); } catch (const std::ssortingng &e) { whaaat += e ; } catch (const char *e) { whaaat += e ; } catch (...) { whaaat += "who knows"; } if (eptr) { whaaat += " ("; num_nested++; goto next; } } whaaat += std::ssortingng(num_nested, ')'); return whaaat; }
la même chose:
Here is WHAT happened: "success!" here is what: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))"
http://coliru.stacked-crooked.com/a/32ec5af5b1d43453
UPD
La fonctionnalité similaire peut être implémentée dans C ++ 03 en utilisant une astuce qui permet de throw
exception courante en dehors du bloc catch: https://stackoverflow.com/a/3641809/5447906
Pas la meilleure solution à mon avis mais semble fonctionner.
try { // code throws potentially unknown exception } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } catch (...) { std::exception_ptr eptr = std::current_exception(); // then what ? LogUnknownException(); }
Merci à ForEveR pour la solution initiale, mais je ne suis pas sûr de vouloir lancer à nouveau dans le bloc.