fork download
  1. #include <iostream>
  2. #include <exception>
  3.  
  4. enum scope_exit_condition {
  5. all, succeed, fail
  6. };
  7.  
  8. template <class F>
  9. class scope_exit_t {
  10. F f;
  11. scope_exit_condition cond;
  12. bool moved;
  13. scope_exit_t(const scope_exit_t&);
  14. void operator=(const scope_exit_t&);
  15. public:
  16. explicit scope_exit_t(F f, scope_exit_condition cond)
  17. : f(f)
  18. , cond(cond)
  19. , moved(false)
  20. {
  21. }
  22.  
  23. scope_exit_t(scope_exit_t&& other)
  24. : f(other.f)
  25. , cond(other.cond)
  26. {
  27. other.moved = true;
  28. }
  29.  
  30. ~scope_exit_t()
  31. {
  32. if (moved)
  33. return;
  34.  
  35. if ((cond == all) || (cond == fail) == std::uncaught_exception())
  36. f();
  37. }
  38. };
  39.  
  40. template <class F>
  41. scope_exit_t<F> scope_exit(F f, scope_exit_condition cond = all)
  42. {
  43. return scope_exit_t<F>(f, cond);
  44. }
  45.  
  46. void foo()
  47. {
  48. std::cout << "== No exception\n";
  49. auto suc = scope_exit([] { std::cout << "Succeed: should appear\n"; }, succeed);
  50. auto fai = scope_exit([] { std::cout << "Failed: should not appear\n"; }, fail);
  51. }
  52.  
  53. void bar()
  54. {
  55. std::cout << "== Exception throwing\n";
  56. auto suc = scope_exit([] { std::cout << "Succeed: should not appear\n"; }, succeed);
  57. auto fai = scope_exit([] { std::cout << "Failed: should appear\n"; }, fail);
  58. throw std::exception();
  59. }
  60.  
  61. int main()
  62. {
  63. try {
  64. foo();
  65. bar();
  66. }
  67. catch(...)
  68. {
  69. }
  70. }
Success #stdin #stdout 0s 3016KB
stdin
Standard input is empty
stdout
== No exception
Succeed: should appear
== Exception throwing
Failed: should appear