1 #pragma once 2 3 #include <optional> 4 #include <utility> 5 6 namespace utils 7 { 8 9 template <class F> 10 struct Ensure 11 { 12 Ensure() = default; 13 14 template <class U> Ensureutils::Ensure15 Ensure(U&& functor) : functor(std::forward<U>(functor)) 16 {} 17 Ensureutils::Ensure18 Ensure(F functor) : functor(std::move(functor)) {} 19 20 Ensure(Ensure&& other) = delete; 21 Ensure(const Ensure&) = delete; 22 ~Ensureutils::Ensure23 ~Ensure() 24 { 25 call(); 26 } 27 28 template <class U> operator =utils::Ensure29 Ensure& operator=(U&& other) 30 { 31 call(); 32 functor = std::move(other); 33 return *this; 34 } 35 36 Ensure& operator=(Ensure&& other) = delete; 37 operator =utils::Ensure38 Ensure& operator=(std::nullptr_t) 39 { 40 call(); 41 functor = std::nullopt; 42 return *this; 43 } 44 45 Ensure& operator=(const Ensure&) = delete; 46 operator boolutils::Ensure47 explicit operator bool() const 48 { 49 return static_cast<bool>(functor); 50 } 51 52 private: callutils::Ensure53 void call() 54 { 55 if (functor) 56 { 57 (*functor)(); 58 } 59 } 60 61 std::optional<F> functor; 62 }; 63 64 } // namespace utils 65