C++ 有没有办法判断程序是否正在抛出异常?

C++ 有没有办法判断程序是否正在抛出异常?,c++,c++11,exception,exception-handling,C++,C++11,Exception,Exception Handling,我问题的简短版本 堆栈上分配了一个类型为A的对象。在它的析构函数~A()中,有没有办法判断调用析构函数是因为抛出了异常并且堆栈正在展开,还是仅仅因为定义它的范围“自然”结束?我试着检查std::current_exception是否为空,是否不起作用 较长版本 我必须支持一个旧的API: void MyApi() { try { MyTimeTracker mtt; //do API stuff } catch(...) {

我问题的简短版本

堆栈上分配了一个类型为A的对象。在它的析构函数~A()中,有没有办法判断调用析构函数是因为抛出了异常并且堆栈正在展开,还是仅仅因为定义它的范围“自然”结束?我试着检查
std::current_exception
是否为空,是否不起作用

较长版本

我必须支持一个旧的API:

void MyApi()
{
    try
    {
        MyTimeTracker mtt;
        //do API stuff
    }
    catch(...)
    {
        //handle exception
    }
}
如果
API stuff
抛出异常,则表示API失败,否则表示成功。MyTimeTracker检查执行
API stuff
所需的时间-它测量构造函数中的开始时间和析构函数中的结束时间,并将其报告给数据库

现在我希望它也报告API调用是否成功。有没有办法在析构函数中说明这一点

我不允许在第一个
try
块之外分配它,因为整个API代码必须在一个try块中。我可以将
API的东西
放在第一个块中的一个单独的try块中,然后重新播放,但这看起来很难看


我尝试在析构函数中检查
std::current_exception
,但它是空的,即使我们正在抛出一个异常。

没有标准的可移植方法来检测堆栈展开的状态,如您所述

但有一个更简单的解决办法。将布尔成员添加到
MyTimeTracker
,如果API成功设置它,然后在析构函数中检查它

MyTimeTracker::MyTimeTracker()
{
    ...
    success = false;
}

MyTimeTracker::~MyTimeTracker()
{
    ...
    if (!success) {
        ... 
    }
}

void MyApi()
{
    try
    {
        MyTimeTracker mtt;
        //do API stuff
        mtt.success = true;
    }
    catch (...)
    {
        //handle exception
    }
}

更新:

这样做的主要原因是报告异常上的错误代码

然后,您必须求助于第二个
try/catch
来获取错误代码,将其存储在
mtt
对象中,以便在析构函数中对其进行操作,然后重试:

MyTimeTracker::MyTimeTracker()
{
    ...
    errCode = 0;
}

MyTimeTracker::~MyTimeTracker()
{
    ...
    if (errCode != 0) {
        ... 
    }
}

void MyApi()
{
    try
    {
        MyTimeTracker mtt;
        try
        {
            //do API stuff
        }
        catch (const the_api_error &e)
        {
            mtt.errCode = ...; // error code from e... 
            throw;
        }
    }
    catch (...)
    {
        //handle exception
    }
}

没有一种标准的便携式方法可以像您描述的那样检测堆栈展开的状态

但有一个更简单的解决办法。将布尔成员添加到
MyTimeTracker
,如果API成功设置它,然后在析构函数中检查它

MyTimeTracker::MyTimeTracker()
{
    ...
    success = false;
}

MyTimeTracker::~MyTimeTracker()
{
    ...
    if (!success) {
        ... 
    }
}

void MyApi()
{
    try
    {
        MyTimeTracker mtt;
        //do API stuff
        mtt.success = true;
    }
    catch (...)
    {
        //handle exception
    }
}

更新:

这样做的主要原因是报告异常上的错误代码

然后,您必须求助于第二个
try/catch
来获取错误代码,将其存储在
mtt
对象中,以便在析构函数中对其进行操作,然后重试:

MyTimeTracker::MyTimeTracker()
{
    ...
    errCode = 0;
}

MyTimeTracker::~MyTimeTracker()
{
    ...
    if (errCode != 0) {
        ... 
    }
}

void MyApi()
{
    try
    {
        MyTimeTracker mtt;
        try
        {
            //do API stuff
        }
        catch (const the_api_error &e)
        {
            mtt.errCode = ...; // error code from e... 
            throw;
        }
    }
    catch (...)
    {
        //handle exception
    }
}

有时,显而易见的简单是如此优雅。这在我的情况下是行不通的。我不想深入讨论细节,但这样做的主要原因是报告异常上的错误代码。唉。谢谢。@remy lebeau似乎
std::uncaught\u exception
就是为了这个目的而设计的:。但是,它不让您看到异常实际上是什么is@Valentin:我以前从未听说过
std::uncaught\u exception()
。但正如你所说,你没有访问实际异常的权限,因此你必须实际捕获它,以便你可以从中复制数据。有时显而易见,简单是如此优雅。在我的情况下,这不起作用。我不想深入讨论细节,但这样做的主要原因是报告异常上的错误代码。唉。谢谢。@remy lebeau似乎
std::uncaught\u exception
就是为了这个目的而设计的:。但是,它不让您看到异常实际上是什么is@Valentin:我以前从未听说过
std::uncaught\u exception()
。但正如您所说,您没有访问实际异常的权限,因此您必须实际捕获它,以便从中复制数据