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> 15 Ensure(U&& functor) : functor(std::forward<U>(functor)) 16 {} 17 18 Ensure(F functor) : functor(std::move(functor)) 19 {} 20 21 Ensure(Ensure&& other) = delete; 22 Ensure(const Ensure&) = delete; 23 24 ~Ensure() 25 { 26 clear(); 27 } 28 29 template <class U> 30 Ensure& operator=(U&& other) 31 { 32 clear(); 33 functor = std::move(other); 34 return *this; 35 } 36 37 Ensure& operator=(Ensure&& other) = delete; 38 39 Ensure& operator=(std::nullptr_t) 40 { 41 clear(); 42 return *this; 43 } 44 45 Ensure& operator=(const Ensure&) = delete; 46 47 explicit operator bool() const 48 { 49 return static_cast<bool>(functor); 50 } 51 52 private: 53 void clear() 54 { 55 if (functor) 56 { 57 (*functor)(); 58 functor = std::nullopt; 59 } 60 } 61 62 std::optional<F> functor; 63 }; 64 65 } // namespace utils 66