This is the code I have.
try { // code throws potentially unknown exception } catch (...) { std::exception_ptr eptr = std::current_exception(); // then what ? }
Ideally, I would like to get the string associated to the exception if it is a std::exception.
// then what ?
here is what:
#include <exception> #include <stdexcept> #include <iostream> #include <string> std::string 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::string &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; } }
what it prints:
Here is WHAT happened: it's success! and now what: who knows
http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24
so this allows to get what
in the catch-all clause.
but what if exception is nested??? here is what:
std::string what(const std::exception_ptr &eptr = std::current_exception()); template <typename T> std::string nested_what(const T &e) { try { std::rethrow_if_nested(e); } catch (...) { return " (" + what(std::current_exception()) + ")"; } return {}; } std::string 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::string &e) { return e ; } catch (const char *e) { return e ; } catch (...) { return "who knows"; } }
using example from here:
#include <fstream> ... // sample function that catches an exception and wraps it in a nested exception void open_file(const std::string& 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; } }
what is printed:
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
but what if recursion too deep? what if stackoverflow? optimized what:
#include <typeinfo> template <typename T> std::exception_ptr get_nested(const T &e) { try { auto &nested = dynamic_cast<const std::nested_exception&>(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::string what(std::exception_ptr eptr = std::current_exception()) { if (!eptr) { throw std::bad_exception(); } std::string 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::string &e) { whaaat += e ; } catch (const char *e) { whaaat += e ; } catch (...) { whaaat += "who knows"; } if (eptr) { whaaat += " ("; num_nested++; goto next; } } whaaat += std::string(num_nested, ')'); return whaaat; }
the same whats:
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
The similar functionality can be implemented in C++03 by using a trick that allows to rethrow
current exception outside of catch block: https://stackoverflow.com/a/3641809/5447906
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With