// // scope_guard.hpp // memory // // Created by Sam Jaffe on 9/24/15. // // #pragma once #include class scope_exit { public: template 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 on_exit_; }; #if __cplusplus > 201402L template class scope_exception { public: template 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 on_exit_; int depth_; }; using scope_failure = scope_exception; using scope_success = scope_exception; #endif #if !defined(CONCAT) #define CONCAT2(A, B) A##B #define CONCAT(A, B) CONCAT2(A, B) #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};