浏览代码

refactor: clean up interfaces, including allowing move, release()

Sam Jaffe 2 年之前
父节点
当前提交
dda916e01f
共有 1 个文件被更改,包括 48 次插入12 次删除
  1. 48 12
      include/scope_guard/scope_guard.hpp

+ 48 - 12
include/scope_guard/scope_guard.hpp

@@ -10,26 +10,62 @@
 
 #include <functional>
 
-struct scope_exit {
-  template <typename F> scope_exit(F f) : _f(f) {}
-  ~scope_exit() noexcept { _f(); }
-  std::function<void()> _f;
+class scope_exit {
+public:
+ template <typename F> scope_exit(F f) : on_exit_(f) {}
+  
+  scope_exit(scope_exit const &) = delete;
+  scope_exit &operator=(scope_exit const &) = delete;
+  scope_exit(scope_exit &&) = default;
+  scope_exit &operator=(scope_exit &&) = default;
+  
+  ~scope_exit() noexcept { if (on_exit_) { on_exit_(); } }
+  
+  void release() { on_exit_ = {}; }
+
+private:
+  std::function<void()> on_exit_;
 };
 
 #if __cplusplus > 201402L
-template <bool B>
-struct scope_exception {
-  template <typename F> scope_exception(F f) : _f(f), _except(std::uncaught_exceptions()) {}
-  ~scope_exception() noexcept(B) { if (B == (std::uncaught_exceptions() > _except)) _f(); }
-  std::function<void()> _f;
-  int const _except;
+template <bool RunOnFailure>
+class scope_exception {
+public:
+  template <typename F>
+  scope_exception(F f) : on_exit_(f), depth_(std::uncaught_exceptions()) {}
+  
+  scope_exception(scope_exception const &) = delete;
+  scope_exception &operator=(scope_exception const &) = delete;
+  scope_exception(scope_exception &&) = default;
+  scope_exception &operator=(scope_exception &&) = default;
+
+  ~scope_exception() noexcept(RunOnFailure) {
+    if (on_exit_ && RunOnFailure == is_failure()) { on_exit_(); }
+  }
+  
+  void release() { on_exit_ = {}; }
+  
+private:
+  bool is_failure() const {
+    return std::uncaught_exceptions() > depth_;
+  }
+  
+private:
+  std::function<void()> on_exit_;
+  int depth_;
 };
 
 using scope_failure = scope_exception<true>;
 using scope_success = scope_exception<false>;
 #endif
 
+#if !defined(CONCAT)
 #define CONCAT2(A, B) A##B
 #define CONCAT(A, B) CONCAT2(A, B)
-#define scope(t) scope_##t CONCAT(inline_scope_guard_##t##_,__LINE__) = [&]()
-#define scope_guard(t, f) scope_##t CONCAT(scope_guard_##t##_,__LINE__){f};
+#endif
+
+#define SCOPE_TYPE(t) CONCAT(scope_,t)
+#define SCOPE_GUARD_NAME(t) CONCAT(CONCAT(scope_guard_,t),__LINE__)
+
+#define scope(t) SCOPE_TYPE(t) SCOPE_GUARD_NAME(t) = [&]()
+#define scope_guard(t, f) SCOPE_TYPE(t) SCOPE_GUARD_NAME(t){f};