blob: bb5a1e02eb19dbfdcffb61c7f5daf8eb2587fb87 [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 {
Michal Orzel6050b652024-12-20 11:43:06 +010025 call();
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010026 }
27
28 template <class U>
29 Ensure& operator=(U&& other)
30 {
Michal Orzel6050b652024-12-20 11:43:06 +010031 call();
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010032 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 {
Michal Orzel6050b652024-12-20 11:43:06 +010040 call();
41 functor = std::nullopt;
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010042 return *this;
43 }
44
45 Ensure& operator=(const Ensure&) = delete;
46
Krzysztof Grobelny973b4bb2022-04-25 17:07:27 +020047 explicit operator bool() const
48 {
49 return static_cast<bool>(functor);
50 }
51
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010052 private:
Michal Orzel6050b652024-12-20 11:43:06 +010053 void call()
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010054 {
55 if (functor)
56 {
57 (*functor)();
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010058 }
59 }
60
61 std::optional<F> functor;
62};
63
64} // namespace utils