c++ - telefonico - hipervinculo numero de telefono
¿Cómo hago una llamada a what() en std:: exception_ptr (4)
Este es el código que tengo.
try
{
// code throws potentially unknown exception
}
catch (...)
{
std::exception_ptr eptr = std::current_exception();
// then what ?
}
Idealmente, me gustaría obtener la cadena asociada a la excepción si es una excepción std ::.
// y que ?
esto es lo que
#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; }
}
lo que imprime:
Here is WHAT happened: it''s success!
and now what: who knows
http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24
por lo que esto permite obtener what
en la cláusula catch-all.
pero que pasa si la excepción esta anidada esto es lo que
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"; }
}
usando el ejemplo de 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; }
}
lo que se imprime:
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
pero ¿y si recursión demasiado profunda? ¿Qué pasa si ? optimizado qué:
#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;
}
lo mismo que es
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 funcionalidad similar se puede implementar en C ++ 03 usando un truco que permite volver a throw
la excepción actual fuera del bloque catch: https://.com/a/3641809/5447906
El uso de std::current_exception
parece un poco exagerado en su caso, ya que no parece querer almacenar o copiar el std::exception_ptr
para su procesamiento posterior (que es su única intención, no ayuda a obtener más información sobre una excepción desconocida de ninguna manera). Si solo desea tratar el caso de una std::exception
, ¿qué pasa con el 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";
}
No es la mejor solución en mi opinión pero parece funcionar.
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();
}
Gracias a ForEveR por la solución inicial, pero no estoy seguro de si quiero lanzar nuevamente dentro del bloque catch.
try
{
std::rethrow_exception(eptr);
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}