Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在std::exception\u ptr上调用what()_C++_Exception_C++11 - Fatal编程技术网

C++ 如何在std::exception\u ptr上调用what()

C++ 如何在std::exception\u ptr上调用what(),c++,exception,c++11,C++,Exception,C++11,这是我的密码 try { // code throws potentially unknown exception } catch (...) { std::exception_ptr eptr = std::current_exception(); // then what ? } 理想情况下,如果异常是std::exception,我希望获取与该异常相关联的字符串。try try { std::rethrow_exception(eptr); } catch

这是我的密码

try
{
// code throws potentially unknown exception
}
catch (...)
{
    std::exception_ptr eptr =  std::current_exception();
        // then what ?
}
理想情况下,如果异常是std::exception,我希望获取与该异常相关联的字符串。

try
try
{
   std::rethrow_exception(eptr);
}
catch (const std::exception& e)
{
   std::cerr << e.what() << std::endl;
}
{ std::返回异常(eptr); } 捕获(const std::exception&e) {
在我看来,std::cerr不是最好的解决方案,但似乎有效

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();
}
试试看
{
//代码引发潜在的未知异常
}
捕获(const std::exception&e)
{

std::cerr在您的情况下,使用
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";
}
试试看
{
//代码引发潜在的未知异常
}
捕获(const std::exception&e)
{
标准:cerr
//然后呢

以下是:

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

因此,这允许在catch-all子句中获取
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;  }
}
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 <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;
}

UPD


类似的功能可以在C++03中实现,方法是使用允许在catch块之外重新抛出当前异常的技巧:

对于异常不是从
std::exception
派生的情况,您可能也应该做些什么……在OP的情况下,由于OP已经是i,所以它是高度冗余的n一个
catch
块。一般来说,我认为这不起作用,因为它可能会干扰已经抛出的异常。@KerrekSB是的,可能我们应该捕获任何异常并打印一些关于“未知错误”的内容…KonradRudolph无论如何,标准上没有其他情况。我们可以编写函数并在一个try/catch块后调用它。最终它似乎根本不需要
std::exception\u ptr
。那么std::exception\u ptr的真正用途是什么?@Ram它的用途是存储和复制一个异常(可能有任意类型)。它是一种拥有智能指针。想象一下它就像一个
std::shared_ptr
,只不过它适用于任何类型的任何异常(这就是它也不提供任何类型信息的原因)。这对于在线程之间传播异常特别有用,例如,
std::promise
需要存储发生的异常,以便稍后在另一个线程中尝试访问
std::future
的值时重试。@Ram最后,每当您想存储抛出的异常以供以后使用时,它都很有用(通常情况下,它会在捕获块结束后被销毁)。请参阅及其相关页面。“在您的情况下似乎有点过头了…”这并没有改变它可能是一个MCVE,或者为了拥有一个代码段而成为一个代码段。这并没有回答这个问题,这对我们这些正在寻找它的人来说真的很沮丧。这将打印(至少)异常类型:std::cout name():“null”)在这里使用
current\u exception
是毫无意义的,它不会添加任何内容。与其使用
dynamic\u cast
-
catch bad\u cast
-
return nullptr
,不如使用
dynamic\u cast
指针,而不是引用。您的意思是在第二个代码块中使用
nested\u what
上一个代码示例有一个嵌套的
num_
计数器,您可以对其进行递增,但从未对其进行过测试。这可能是无用的,或者您想以某个数字打破循环?另外,使用(;;)的
可以很容易地删除您的
goto
循环和
中断
eptr==nullptr
时。我们为什么需要重新显示它?有一个建议为std::exception\u ptr添加类型内省:
#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))"