diff --git a/scopeguard.h b/scopeguard.h new file mode 100644 index 0000000..1aa12ed --- /dev/null +++ b/scopeguard.h @@ -0,0 +1,60 @@ +#ifndef SCOPEGUARD_H +#define SCOPEGUARD_H + +template +class ScopeGuard { + Fun f_; + bool active_; +public: + ScopeGuard(Fun f) + : f_(std::move(f)) + , active_(true) { + } + + ~ScopeGuard() { if(active_) f_(); } + + void dismiss() { active_=false; } + + ScopeGuard() = delete; + ScopeGuard(const ScopeGuard&) = delete; + ScopeGuard& operator=(const ScopeGuard&) = delete; + ScopeGuard(ScopeGuard&& rhs) + : f_(std::move(rhs.f_)) + , active_(rhs.active_) + { + rhs.dismiss(); + } +}; + +template +ScopeGuard scopeGuard(Fun f) +{ + return ScopeGuard(std::move(f)); +} + +namespace ScopeGuard_detail { + + enum class ScopeGuardOnExit {}; + + template + ScopeGuard operator+(ScopeGuardOnExit, Fun&& fn) { + return ScopeGuard(std::forward(fn)); + } + +} + +#define CONCATENATE_IMPL(s1, s2) s1##s2 +#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) +#ifdef __COUNTER__ +#define ANONYMOUS_VARIABLE(str) \ + CONCATENATE(str,__COUNTER__) +#else +#define ANONYMOUS_VARIABLE(str) \ + CONCATENATE(str,__LINE__) +#endif + +#define SCOPE_EXIT \ + auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ + = ::ScopeGuard_detail::ScopeGuardOnExit() + [&]() + +#endif // SCOPEGUARD_H