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 private: 57 void clear() 58 { 59 if (functor) 60 { 61 (*functor)(); 62 functor = std::nullopt; 63 } 64 } 65 66 std::optional<F> functor; 67 }; 68 69 } // namespace utils 70