blob: 8b7567e72ba7a929e39a1f6c8776f74d53860c30 [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
Patrick Williams3a1c2972023-05-10 07:51:04 -050018 Ensure(F functor) : functor(std::move(functor)) {}
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010019
Szymon Dompkebcf045a2022-09-16 15:23:30 +020020 Ensure(Ensure&& other) = delete;
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010021 Ensure(const Ensure&) = delete;
22
23 ~Ensure()
24 {
25 clear();
26 }
27
28 template <class U>
29 Ensure& operator=(U&& other)
30 {
31 clear();
32 functor = std::move(other);
33 return *this;
34 }
35
Szymon Dompkebcf045a2022-09-16 15:23:30 +020036 Ensure& operator=(Ensure&& other) = delete;
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010037
38 Ensure& operator=(std::nullptr_t)
39 {
40 clear();
41 return *this;
42 }
43
44 Ensure& operator=(const Ensure&) = delete;
45
Krzysztof Grobelny973b4bb2022-04-25 17:07:27 +020046 explicit operator bool() const
47 {
48 return static_cast<bool>(functor);
49 }
50
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010051 private:
52 void clear()
53 {
54 if (functor)
55 {
56 (*functor)();
57 functor = std::nullopt;
58 }
59 }
60
61 std::optional<F> functor;
62};
63
64} // namespace utils