#include <iostream>
#include <exception>
enum scope_exit_condition {
all, succeed, fail
};
template <class F>
class scope_exit_t {
F f;
scope_exit_condition cond;
bool moved;
scope_exit_t(const scope_exit_t&);
void operator=(const scope_exit_t&);
public:
explicit scope_exit_t(F f, scope_exit_condition cond)
: f(f)
, cond(cond)
, moved(false)
{
}
scope_exit_t(scope_exit_t&& other)
: f(other.f)
, cond(other.cond)
{
other.moved = true;
}
~scope_exit_t()
{
if (moved)
return;
if ((cond == all) || (cond == fail) == std::uncaught_exception())
f();
}
};
template <class F>
scope_exit_t<F> scope_exit(F f, scope_exit_condition cond = all)
{
return scope_exit_t<F>(f, cond);
}
void foo()
{
std::cout << "== No exception\n";
auto suc = scope_exit([] { std::cout << "Succeed: should appear\n"; }, succeed);
auto fai = scope_exit([] { std::cout << "Failed: should not appear\n"; }, fail);
}
void bar()
{
std::cout << "== Exception throwing\n";
auto suc = scope_exit([] { std::cout << "Succeed: should not appear\n"; }, succeed);
auto fai = scope_exit([] { std::cout << "Failed: should appear\n"; }, fail);
throw std::exception();
}
int main()
{
try {
foo();
bar();
}
catch(...)
{
}
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZXhjZXB0aW9uPgoKZW51bSBzY29wZV9leGl0X2NvbmRpdGlvbiB7CiAgICBhbGwsIHN1Y2NlZWQsIGZhaWwKfTsKCnRlbXBsYXRlIDxjbGFzcyBGPgpjbGFzcyBzY29wZV9leGl0X3QgewoJRiBmOwoJc2NvcGVfZXhpdF9jb25kaXRpb24gY29uZDsKCWJvb2wgbW92ZWQ7CglzY29wZV9leGl0X3QoY29uc3Qgc2NvcGVfZXhpdF90Jik7Cgl2b2lkIG9wZXJhdG9yPShjb25zdCBzY29wZV9leGl0X3QmKTsKcHVibGljOgoJZXhwbGljaXQgc2NvcGVfZXhpdF90KEYgZiwgc2NvcGVfZXhpdF9jb25kaXRpb24gY29uZCkKCQk6IGYoZikKCQksIGNvbmQoY29uZCkKCQksIG1vdmVkKGZhbHNlKQoJewoJfQoKCXNjb3BlX2V4aXRfdChzY29wZV9leGl0X3QmJiBvdGhlcikKCQk6IGYob3RoZXIuZikKCQksIGNvbmQob3RoZXIuY29uZCkKCXsKCQlvdGhlci5tb3ZlZCA9IHRydWU7Cgl9CgoJfnNjb3BlX2V4aXRfdCgpCgl7CQoJCWlmIChtb3ZlZCkKCQkJcmV0dXJuOwoKCQlpZiAoKGNvbmQgPT0gYWxsKSB8fCAoY29uZCA9PSBmYWlsKSA9PSBzdGQ6OnVuY2F1Z2h0X2V4Y2VwdGlvbigpKQoJCQlmKCk7Cgl9Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgRj4Kc2NvcGVfZXhpdF90PEY+IHNjb3BlX2V4aXQoRiBmLCBzY29wZV9leGl0X2NvbmRpdGlvbiBjb25kID0gYWxsKQp7CglyZXR1cm4gc2NvcGVfZXhpdF90PEY+KGYsIGNvbmQpOwp9Cgp2b2lkIGZvbygpCnsKCXN0ZDo6Y291dCA8PCAiPT0gTm8gZXhjZXB0aW9uXG4iOwoJYXV0byBzdWMgPSBzY29wZV9leGl0KFtdIHsgc3RkOjpjb3V0IDw8ICJTdWNjZWVkOiBzaG91bGQgYXBwZWFyXG4iOyB9LCBzdWNjZWVkKTsKCWF1dG8gZmFpID0gc2NvcGVfZXhpdChbXSB7IHN0ZDo6Y291dCA8PCAiRmFpbGVkOiBzaG91bGQgbm90IGFwcGVhclxuIjsgfSwgZmFpbCk7Cn0KCnZvaWQgYmFyKCkKewoJc3RkOjpjb3V0IDw8ICI9PSBFeGNlcHRpb24gdGhyb3dpbmdcbiI7CglhdXRvIHN1YyA9IHNjb3BlX2V4aXQoW10geyBzdGQ6OmNvdXQgPDwgIlN1Y2NlZWQ6IHNob3VsZCBub3QgYXBwZWFyXG4iOyB9LCBzdWNjZWVkKTsKCWF1dG8gZmFpID0gc2NvcGVfZXhpdChbXSB7IHN0ZDo6Y291dCA8PCAiRmFpbGVkOiBzaG91bGQgYXBwZWFyXG4iOyB9LCBmYWlsKTsKCXRocm93IHN0ZDo6ZXhjZXB0aW9uKCk7Cn0KCmludCBtYWluKCkKewoJdHJ5IHsKCQlmb28oKTsKCQliYXIoKTsKCX0KCWNhdGNoKC4uLikKCXsJCQoJfQp9