为什么Alexandrescu不能使用std :: uncaught_exception()在ScopeGuard11中实现SCOPE_FAIL? [英] Why can't Alexandrescu use std::uncaught_exception() to implement SCOPE_FAIL in ScopeGuard11?

查看:244
本文介绍了为什么Alexandrescu不能使用std :: uncaught_exception()在ScopeGuard11中实现SCOPE_FAIL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很多人都很熟悉Alexandrescus ScopeGuard先生的模板(现在是Loki的一部分)和这里提供的新版本ScopeGuard11:
http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012 -Andrei-Alexandrescu-Systematic-Error-Handling-in-C

Many people are no doubt familiar with Mr. Alexandrescus ScopeGuard template (now part of Loki) and the new version ScopeGuard11 presented here: http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C

源代码:
https://gist.github.com/KindDragon/4650442

在他的c ++及更高版本的演讲2012他提到他找不到一种方法来正确检测范围是否由于异常而退出。因此,当且仅当由于异常而退出范围时,他无法实现一个SCOPE_FAIL宏,它将执行提供的lambda(通常用于回滚代码)。这将使dismiss()成员函数不需要,并使代码更可读。

In his talk at c++ and beyond 2012 he mentioned that he couldn't find a way to correctly detect if scope was being exited because of an exception. Therefore he couldn't implement a SCOPE_FAIL macro which would execute the supplied lambda (usually used for roll back code) if and only if the scope exited because of an exception. This would render the dismiss() member function unneeded and make code more readable.

由于我绝对不是天才或有经验的Alexandrescu先生我期望实现SCOPE_FAIL不是那么容易:

Since I am by no means as genius or experienced as Mr. Alexandrescu I expect implementing SCOPE_FAIL is not as easy as this:

~ScopeGuard11(){                      //destructor
    if(std::uncaught_exception()){    //if we are exiting because of an exception
        f_();                         //execute the functor
    }
    //otherwise do nothing
}

我的问题是为什么不呢?

My question is why not?

推荐答案

使用 ScopeGuard11 类,它有你的析构函数,成员 f _ 可以被调用,即使它不是当前范围(应该由保护)到异常。

With a ScopeGuard11 class that has your destructor, the member f_ may be called, even if it is not the current scope (that is supposed to be protected by the guard) that is being exited due to an exception. Use of this guard is unsafe in code that might be used during exception cleanup.

尝试此示例:

#include <exception>
#include <iostream>
#include <string>

// simplified ScopeGuard11
template <class Fun>
struct ScopeGuard11 {
     Fun f_;
     ScopeGuard11(Fun f) : f_(f) {}
     ~ScopeGuard11(){                      //destructor
        if(std::uncaught_exception()){    //if we are exiting because of an exception
            f_();                         //execute the functor
         }
         //otherwise do nothing
      }
};

void rollback() {
  std::cout << "Rolling back everything\n";
}
void could_throw(bool doit) {
  if (doit) throw std::string("Too bad");
}

void foo() {
   ScopeGuard11<void (*)()> rollback_on_exception(rollback);
   could_throw(false);
   // should never see a rollback here
   // as could throw won't throw with this argument
   // in reality there might sometimes be exceptions
   // but here we care about the case where there is none 
}

struct Bar {
   ~Bar() {
      // to cleanup is to foo
      // and never throw from d'tor
      try { foo(); } catch (...) {}
   }
};

void baz() {
   Bar bar;
   ScopeGuard11<void (*)()> more_rollback_on_exception(rollback);
   could_throw(true);
}

int main() try {
   baz();
} catch (std::string & e) {
   std::cout << "caught: " << e << std::endl;
}

你会想要看到一个 code>,当你离开 baz 时,你会看到两个 - 包括一个离开 foo

You'd want to see one rollback when leaving baz, but you'll see two - including a spurious one from leaving foo.

这篇关于为什么Alexandrescu不能使用std :: uncaught_exception()在ScopeGuard11中实现SCOPE_FAIL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆