如何调用std :: exception_ptr上的what()

Ram*_*Ram 28 c++ exception c++11

这是我的代码.

try
{
// code throws potentially unknown exception
}
catch (...)
{
    std::exception_ptr eptr =  std::current_exception();
        // then what ?
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,如果它是std :: exception,我想获得与异常相关联的字符串.

For*_*veR 18

try
{
   std::rethrow_exception(eptr);
}
catch (const std::exception& e)
{
   std::cerr << e.what() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 你可能应该做的事情是异常*不*从`std :: exception`派生出来...... (6认同)

ant*_*_rh 17

//那又怎样?

这是什么:

#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;  }
}
Run Code Online (Sandbox Code Playgroud)

什么打印:

Here is WHAT happened: it's success!
and now what: who knows
Run Code Online (Sandbox Code Playgroud)

http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24

所以这允许进入whatcatch-all子句.

但如果异常嵌套怎么办?这是什么:

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"; }
}
Run Code Online (Sandbox Code Playgroud)

使用此处的示例:

#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;  }
}
Run Code Online (Sandbox Code Playgroud)

印刷什么:

Here is WHAT happened: "success!"
what happened for run: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))"
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

同样的事情:

Here is WHAT happened: "success!"
here is what: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))"
Run Code Online (Sandbox Code Playgroud)

http://coliru.stacked-crooked.com/a/32ec5af5b1d43453

UPD

通过使用允许throw在catch块之外重新获得当前异常的技巧,可以在C++ 03中实现类似的功能:https://stackoverflow.com/a/3641809/5447906


Chr*_*ica 11

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 exception\n";
}
Run Code Online (Sandbox Code Playgroud)

  • @Ram用于存储和复制异常(可能具有任意类型).它是一种拥有智能指针.想象一下它就像`std :: shared_ptr <std :: exception>`,只是它适用于任何类型的任何异常(这也就是它不提供任何类型信息的原因).这对于在线程之间传播异常特别有用,例如`std :: promise`需要*存储*一个发生的异常,以便在以后尝试访问另一个线程中的`std :: future`值时重新抛出. (9认同)
  • @Ram最后,只要你想存储抛出的异常供以后使用(通常它会在catch块结束后销毁),它就很有用.参见[this](http://en.cppreference.com/w/cpp/error/exception_ptr)及其相关页面. (2认同)
  • “似乎在您的案例中有点过头……”这并没有改变,因为它很容易是MCVE或代码段(为了具有代码段的缘故)。这并不能回答问题,这确实使我们中正在寻找这个问题的人感到沮丧。 (2认同)