Comment faire un appel à what () sur std :: exception_ptr

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; } 

http://en.cppreference.com/w/cpp/error/exception_ptr

// 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.