scope-guard.hpp 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /*
  2. * Based on Loki::ScopeGuard
  3. */
  4. #pragma once
  5. #include <utility>
  6. namespace scope_guard_util {
  7. template<typename FunctionType> class ScopeGuard {
  8. public:
  9. void dismiss() noexcept { dismissed_ = true; }
  10. explicit ScopeGuard(const FunctionType &fn) : function_(fn) {}
  11. explicit ScopeGuard(FunctionType &&fn) : function_(std::move(fn)) {}
  12. ScopeGuard(ScopeGuard &&other) : dismissed_(other.dismissed_), function_(std::move(other.function_))
  13. {
  14. other.dismissed_ = true;
  15. }
  16. ~ScopeGuard() noexcept
  17. {
  18. if (!dismissed_)
  19. execute();
  20. }
  21. private:
  22. void *operator new(size_t) = delete;
  23. void execute() noexcept { function_(); }
  24. bool dismissed_ = false;
  25. FunctionType function_;
  26. };
  27. template<typename FunctionType> ScopeGuard<typename std::decay<FunctionType>::type> make_guard(FunctionType &&fn)
  28. {
  29. return ScopeGuard<typename std::decay<FunctionType>::type>{std::forward<FunctionType>(fn)};
  30. }
  31. namespace detail {
  32. enum class ScopeGuardOnExit {};
  33. template<typename FunctionType>
  34. ScopeGuard<typename std::decay<FunctionType>::type> operator+(detail::ScopeGuardOnExit, FunctionType &&fn)
  35. {
  36. return ScopeGuard<typename std::decay<FunctionType>::type>(std::forward<FunctionType>(fn));
  37. }
  38. } // namespace detail
  39. } // namespace scope_guard_util
  40. #define SCOPE_EXIT_CONCAT2(x, y) x##y
  41. #define SCOPE_EXIT_CONCAT(x, y) SCOPE_EXIT_CONCAT2(x, y)
  42. #define SCOPE_EXIT \
  43. auto SCOPE_EXIT_CONCAT(SCOPE_EXIT_STATE, __LINE__) = \
  44. ::scope_guard_util::detail::ScopeGuardOnExit() + [&]() noexcept