gpt4 book ai didi

c++ - 为什么 Alexandrescu 不能使用 std::uncaught_exception() 在 ScopeGuard11 中实现 SCOPE_FAIL?

转载 作者:IT老高 更新时间:2023-10-28 22:14:36 25 4
gpt4 key购买 nike

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

这里有来源: https://gist.github.com/KindDragon/4650442

在 2012 年及以后的 c++ 演讲中,他提到他无法找到正确检测范围是否因异常而退出的方法。因此,当且仅当范围因异常而退出时,他无法实现 SCOPE_FAIL 宏,该宏将执行提供的 lambda(通常用于回滚代码)。这将使dismiss() 成员函数变得不需要,并使代码更具可读性。

由于我绝不像 Alexandrescu 先生那样天才或经验丰富,我预计实现 SCOPE_FAIL 并不像这样容易:

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

我的问题是为什么不呢?

最佳答案

使用具有析构函数的 ScopeGuard11 类,可以调用成员 f_,即使它不是当前作用域(应该由由于异常而退出的守卫)。在异常清理期间可能使用的代码中使用此保护是不安全的。

试试这个例子:

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

您希望在离开 baz 时看到一个 rollback,但您会看到两个 - 包括离开 foo 时的虚假回滚.

关于c++ - 为什么 Alexandrescu 不能使用 std::uncaught_exception() 在 ScopeGuard11 中实现 SCOPE_FAIL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14927328/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com