|
15 | 15 | #include <version> |
16 | 16 |
|
17 | 17 | #if (!(defined(__cpp_concepts) || !(defined(__cpp_lib_concepts)))) |
18 | | - static_assert(false, "C++20 Concepts Required"); |
| 18 | +static_assert(false, "C++20 Concepts Required"); |
19 | 19 | #endif |
20 | 20 |
|
21 | 21 |
|
22 | | - |
23 | 22 | #include <concepts> |
24 | 23 | #include <functional> |
25 | 24 | #include <exception> |
@@ -112,56 +111,63 @@ template<scope_exit_function ScopeExitFunc, scope_invoke_checker InvokeChecker = |
112 | 111 | class [[nodiscard]] scope_guard |
113 | 112 | { |
114 | 113 | public: |
115 | | - explicit constexpr scope_guard(ScopeExitFunc&& exit_func) |
116 | | - // Is the noexcept depending only on scope_exit construct or also on invoke_checker construct? |
117 | | - noexcept(std::is_nothrow_constructible_v<ScopeExitFunc>) |
118 | | - //noexcept(std::is_nothrow_constructible_v<ScopeExitFunc> && std::is_nothrow_constructible_v<InvokeChecker>) |
119 | | - requires (!std::is_same_v<decltype(exit_func), scope_guard>) |
| 114 | + template<typename T, typename S> |
| 115 | + explicit constexpr scope_guard(T&& exit_func, S&& invoke_checker) |
| 116 | + noexcept(std::is_nothrow_constructible_v<ScopeExitFunc> && std::is_nothrow_constructible_v<InvokeChecker>) |
120 | 117 | try |
121 | | - : m_exit_func(std::forward<ScopeExitFunc>(exit_func)) |
| 118 | + : m_exit_func(std::forward<T>(exit_func)), |
| 119 | + m_invoke_checker{ std::forward<S>(invoke_checker) } |
122 | 120 | {} |
123 | 121 | catch (...) |
124 | 122 | { |
125 | 123 | if constexpr (!std::is_nothrow_constructible_v<ScopeExitFunc>) |
126 | 124 | { |
127 | 125 | if constexpr (!HasDontInvokeOnCreationException<ScopeExitFunc>) |
128 | 126 | { |
129 | | - // Can we call the invoke_checker?? we don't know who threw the exception? (exit_func or invoke_checker default construct?) |
130 | | - |
131 | 127 | exit_func(); |
132 | 128 | } |
133 | 129 |
|
134 | 130 | throw; |
135 | 131 | } |
136 | 132 | } |
137 | 133 |
|
138 | | - explicit constexpr scope_guard(ScopeExitFunc&& exit_func, InvokeChecker&& invoke_checker) |
| 134 | + |
| 135 | + template<typename T> |
| 136 | + explicit constexpr scope_guard(T&& exit_func) |
| 137 | + // Is the noexcept depending only on scope_exit construct or also on invoke_checker construct? |
| 138 | + //noexcept(std::is_nothrow_constructible_v<ScopeExitFunc>) |
139 | 139 | noexcept(std::is_nothrow_constructible_v<ScopeExitFunc> && std::is_nothrow_constructible_v<InvokeChecker>) |
| 140 | + requires (!std::is_same_v<decltype(exit_func), scope_guard>) |
140 | 141 | try |
141 | | - : m_exit_func(std::forward<ScopeExitFunc>(exit_func)), |
142 | | - m_invoke_checker{ std::forward<InvokeChecker>(invoke_checker) } |
| 142 | + : m_exit_func(std::forward<T>(exit_func)) |
143 | 143 | {} |
144 | 144 | catch (...) |
145 | 145 | { |
146 | 146 | if constexpr (!std::is_nothrow_constructible_v<ScopeExitFunc>) |
147 | 147 | { |
148 | 148 | if constexpr (!HasDontInvokeOnCreationException<ScopeExitFunc>) |
149 | 149 | { |
| 150 | + // Can we call the invoke_checker?? we don't know who threw the exception? (exit_func or invoke_checker default construct?) |
| 151 | + |
150 | 152 | exit_func(); |
151 | 153 | } |
152 | 154 |
|
153 | 155 | throw; |
154 | 156 | } |
155 | 157 | } |
156 | 158 |
|
| 159 | + |
157 | 160 | explicit constexpr scope_guard(scope_guard&& rhs) noexcept(std::is_nothrow_move_constructible_v<ScopeExitFunc> |
158 | 161 | && std::is_nothrow_move_constructible_v<InvokeChecker>) |
| 162 | + requires (HasRelease<InvokeChecker> || HasStaticRelease<InvokeChecker>) |
159 | 163 | : m_exit_func { std::move(rhs.m_exit_func) }, |
160 | 164 | m_invoke_checker { std::move(rhs.m_invoke_checker) } |
161 | 165 | { |
| 166 | + rhs.release(); |
162 | 167 | //rhs.m_invoke_checker = NeverExecute {}; |
163 | 168 | } |
164 | 169 |
|
| 170 | + |
165 | 171 | scope_guard(const scope_guard&) = delete; |
166 | 172 | scope_guard& operator=(const scope_guard&) = delete; |
167 | 173 | scope_guard& operator=(scope_guard&&) = delete; |
@@ -212,12 +218,12 @@ class [[nodiscard]] scope_guard |
212 | 218 |
|
213 | 219 | //================================================================================================== |
214 | 220 |
|
215 | | -template<std::invocable ExitFunc> |
216 | | -scope_guard(ExitFunc&&) -> scope_guard<ExitFunc>; |
217 | | - |
218 | 221 | template<std::invocable ExitFunc, scope_invoke_checker InvokeChecker> |
219 | 222 | scope_guard(ExitFunc&&, InvokeChecker&&) -> scope_guard<ExitFunc, InvokeChecker>; |
220 | 223 |
|
| 224 | +template<std::invocable ExitFunc> |
| 225 | +scope_guard(ExitFunc&&) -> scope_guard<ExitFunc>; |
| 226 | + |
221 | 227 | //================================================================================================== |
222 | 228 |
|
223 | 229 | class ExecuteAlways |
@@ -329,15 +335,19 @@ class Releasable<InvokeChecker> |
329 | 335 |
|
330 | 336 | //================================================================================================== |
331 | 337 |
|
| 338 | + |
332 | 339 | template<class ExitFunc> |
333 | 340 | using scope_exit = scope_guard<ExitFunc, Releasable<>>; |
334 | 341 |
|
| 342 | + |
335 | 343 | template<class ExitFunc> |
336 | 344 | using scope_success = scope_guard<ExitFunc, Releasable<ExecuteWhenNoException>>; |
337 | 345 |
|
| 346 | + |
338 | 347 | template<class ExitFunc> |
339 | 348 | using scope_fail = scope_guard<ExitFunc, Releasable<ExecuteOnlyWhenException>>; |
340 | 349 |
|
| 350 | + |
341 | 351 | //================================================================================================== |
342 | 352 |
|
343 | 353 | // |
|
0 commit comments