如何在std::exception_ptr上调用what()
How do I make a call to what() on std::exception_ptr
这是我的代码。
try
{
// code throws potentially unknown exception
}
catch (...)
{
std::exception_ptr eptr = std::current_exception();
// then what ?
}
理想情况下,如果异常是std::异常,我希望获得与该异常相关联的字符串。
//然后呢?
这是什么:
#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; }
}
打印内容:
Here is WHAT happened: it's success!
and now what: who knows
http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24
因此这允许在catch-all子句中获得CCD_ 1。
但若嵌套了异常怎么办???这是什么:
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"; }
}
使用这里的示例:
#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; }
}
打印内容:
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
但是如果递归太深呢?如果stackoverflow呢?优化内容:
#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;
}
相同的东西:
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
类似的功能可以在C++03中通过使用一个技巧来实现,该技巧允许在catch块之外重新throw
当前异常:https://stackoverflow.com/a/3641809/5447906
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
在您的情况下,使用std::current_exception
似乎有点过头了,因为您似乎不想存储或复制std::exception_ptr
以供以后处理(这是它的唯一目的,它无论如何都无助于获得有关未知异常的附加信息(。如果你只想治疗std::exception
的情况,那么简单的呢
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 exceptionn";
}
在我看来不是最好的解决方案,但似乎有效。
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();
}
感谢ForEveR的初步解决方案,但我不确定我是否想再次在接球块内投球。
相关文章:
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 在抛出 'std::runtime_error' 的实例后终止调用 what(): Filebuf 和 ostream 的 I/O 错误
- 在抛出 what() 的实例后调用'std::logic_error'终止:basic_string::_M_construct 空无效
- 在抛出 'std::invalid_argument' 的实例后终止调用 what(): stoi (找不到问题所在)
- 获取错误:在抛出"std::bad::alloc"的实例后终止调用 what(): std::bad_alloc
- 在抛出 'std::bad_weak_ptr' 的实例后终止调用 what(): bad_weak_ptr?
- 在抛出 'std::regex_error' 的实例后调用终止 what(): 括号未关闭
- 在抛出 'std::invalid_argument' 的实例后调用终止 what(): stoi 错误 in leet
- 在抛出 'std::out_of_range' 的实例后调用的 C++ 终止 what(): basic_string::substr:
- 如何修复抛出"std::logic_error"实例后调用的终止 what(): basic_string::_M_construct null 无效
- 如何在抛出未处理的自定义异常后调用 what()?
- 在抛出 'std::out_of_range' what(): vector::_M_range_check 的实例后调用的终止
- 抛出 'std::logic_error' what() 的实例后调用的终止:basic_string::_S_construct null 无效
- C++抛出"std::length_error"实例后调用的终止,what(): basic_string::_M_create
- 抛出 'std::out_of_range' what() 的实例后调用的终止:basic_string::substr
- C++ 中的文件 IO 出错。在抛出 'std::length_error' 的实例后调用的终止 what(): basic_string::调整大小
- 在抛出 'std::out_of_range' what() 的实例后调用的终止:basic_string::擦除
- 如何避免错误:在抛出 what() 的实例后终止调用'std::logic_error':basic_string::_S_construct null 无效
- 在抛出"std::invalid_argument"的实例后终止调用 what(): dataItem 已在树中 中止(核心转储)
- 如何在std::exception_ptr上调用what()