scope-guard.hpp 1.5 KB

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