blob: 8f266abaf002d3126eaa8a65ca6cab200afd5f7d [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
Krzysztof Grobelny973b4bb2022-04-25 17:07:27 +020056 explicit operator bool() const
57 {
58 return static_cast<bool>(functor);
59 }
60
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010061 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