#pragma once #include #include #include namespace jvalidate::detail { /** * @brief An object representing a cleanup function, to be called as if it was * a destructor for the current function scope. Similar to e.g. D-lang's * scope(exit) or @see https://en.cppreference.com/w/cpp/experimental/scope_exit * * Is movable - allowing us to return this scope object from its constructing * context into the actual owning context that wants to control that scope. */ class OnBlockExit { private: std::function callback_; public: OnBlockExit() = default; template requires std::constructible_from, F> explicit(false) OnBlockExit(F && callback) : callback_(std::forward(callback)) {} OnBlockExit(OnBlockExit const &) = delete; OnBlockExit & operator=(OnBlockExit const &) = delete; // Must be explicity implemented because function's move ctor is non-destructive OnBlockExit(OnBlockExit && other) noexcept { std::swap(other.callback_, callback_); } // Must be explicity implemented because function's move-assign is non-destructive OnBlockExit & operator=(OnBlockExit && other) noexcept { std::swap(other.callback_, callback_); return *this; } ~OnBlockExit() { if (callback_) { callback_(); } } }; }