blob: cbe69c5f1ab1578d1d82050431ce6fc189c55ef4 [file] [log] [blame]
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +01001#pragma once
2
3#include <optional>
4#include <utility>
5
6namespace utils
7{
8
9template <class F>
10struct 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