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