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