1#ifndef A2100C2E_3B3D_4875_ACA4_BFEF2E5B6120
2#define A2100C2E_3B3D_4875_ACA4_BFEF2E5B6120
39template<
typename Self,
typename What,
typename From>
40concept can_construct_from = !std::is_same_v<std::remove_cvref_t<From>, Self> && std::constructible_from<What, From>;
42template<
typename Self,
typename What,
typename From>
43concept can_move_construct_from_noexcept = can_construct_from<Self, What, From> && !std::is_lvalue_reference_v<From> &&
44 std::is_nothrow_constructible_v<What, From>;
47T&& conditional_forward(T&& t, std::true_type)
49 return std::forward<T>(t);
53const T& conditional_forward(T&& t, std::false_type)
87template<
typename ExitFunc>
88class [[nodiscard(
"The object must be used to ensure the exit function is called on scope exit.")]]
exit_action {
107 template<
typename Func>
108 requires(detail::can_construct_from<exit_action, ExitFunc, Func>)
111 )
noexcept(std::is_nothrow_constructible_v<ExitFunc, Func> || std::is_nothrow_constructible_v<ExitFunc, Func&>)
114 detail::conditional_forward(
115 std::forward<Func>(fn),
117 std::is_nothrow_constructible_v<ExitFunc, Func> && !std::is_lvalue_reference_v<Func>>()
140 template<
typename Func>
141 requires(detail::can_move_construct_from_noexcept<exit_action, ExitFunc, Func>)
142 explicit exit_action(Func&& fn) noexcept : m_exit_function(std::forward<Func>(fn))
166 )
noexcept(std::is_nothrow_move_constructible_v<ExitFunc> || std::is_nothrow_copy_constructible_v<ExitFunc>)
167 requires(std::is_nothrow_move_constructible_v<ExitFunc> || std::is_copy_constructible_v<ExitFunc>)
169 detail::conditional_forward(
170 std::forward<ExitFunc>(other.m_exit_function),
171 std::bool_constant<std::is_nothrow_move_constructible_v<ExitFunc>>()
174 m_is_armed(other.m_is_armed)
194 if (this->m_is_armed) {
195 this->m_exit_function();
207 void release() noexcept { this->m_is_armed =
false; }
210 ExitFunc m_exit_function;
211 bool m_is_armed =
true;
219template<
typename ExitFunc>
245template<
typename ExitFunc>
246class [[nodiscard(
"The object must be used to ensure the exit function is called due to an exception.")]]
fail_action {
268 template<
typename Func>
269 requires(detail::can_construct_from<fail_action, ExitFunc, Func>)
272 )
noexcept(std::is_nothrow_constructible_v<ExitFunc, Func> || std::is_nothrow_constructible_v<ExitFunc, Func&>)
275 detail::conditional_forward(
276 std::forward<Func>(fn),
278 std::is_nothrow_constructible_v<ExitFunc, Func> && !std::is_lvalue_reference_v<Func>>()
301 template<
typename Func>
302 requires(detail::can_move_construct_from_noexcept<fail_action, ExitFunc, Func>)
303 explicit fail_action(Func&& fn) noexcept : m_exit_function(std::forward<Func>(fn))
328 )
noexcept(std::is_nothrow_move_constructible_v<ExitFunc> || std::is_nothrow_copy_constructible_v<ExitFunc>)
329 requires(std::is_nothrow_move_constructible_v<ExitFunc> || std::is_copy_constructible_v<ExitFunc>)
331 detail::conditional_forward(
332 std::forward<ExitFunc>(other.m_exit_function),
333 std::bool_constant<std::is_nothrow_move_constructible_v<ExitFunc>>()
336 m_uncaught_exceptions_count(other.m_uncaught_exceptions_count)
360 if (std::uncaught_exceptions() > this->m_uncaught_exceptions_count) {
361 this->m_exit_function();
374 void release() noexcept { this->m_uncaught_exceptions_count = std::numeric_limits<int>::max(); }
377 ExitFunc m_exit_function;
378 int m_uncaught_exceptions_count = std::uncaught_exceptions();
386template<
typename ExitFunc>
416template<
typename ExitFunc>
418 "The object must be used to ensure the exit function is called on a clean scope exit."
441 template<
typename Func>
442 requires(detail::can_construct_from<success_action, ExitFunc, Func>)
445 )
noexcept(std::is_nothrow_constructible_v<ExitFunc, Func> || std::is_nothrow_constructible_v<ExitFunc, Func&>)
447 detail::conditional_forward(
448 std::forward<Func>(fn),
450 std::is_nothrow_constructible_v<ExitFunc, Func> && !std::is_lvalue_reference_v<Func>>()
470 template<
typename Func>
471 requires detail::can_move_construct_from_noexcept<success_action, ExitFunc, Func>
472 explicit success_action(Func&& fn) noexcept : m_exit_function(std::forward<Func>(fn))
497 )
noexcept(std::is_nothrow_move_constructible_v<ExitFunc> || std::is_nothrow_copy_constructible_v<ExitFunc>)
498 requires(std::is_nothrow_move_constructible_v<ExitFunc> || std::is_copy_constructible_v<ExitFunc>)
500 detail::conditional_forward(
501 std::forward<ExitFunc>(other.m_exit_function),
502 std::bool_constant<std::is_nothrow_move_constructible_v<ExitFunc>>()
505 m_uncaught_exceptions_count(other.m_uncaught_exceptions_count)
532 if (std::uncaught_exceptions() <= this->m_uncaught_exceptions_count) {
533 this->m_exit_function();
545 void release() noexcept { this->m_uncaught_exceptions_count = std::numeric_limits<int>::min(); }
548 ExitFunc m_exit_function;
549 int m_uncaught_exceptions_count = std::uncaught_exceptions();
557template<
typename ExitFunc>
A scope guard that calls its exit function on destruction, when a scope is exited.
exit_action(Func &&fn) noexcept
Constructs a new exit_action from an exit function of type Func.
exit_action(exit_action &&other) noexcept(std::is_nothrow_move_constructible_v< ExitFunc >||std::is_nothrow_copy_constructible_v< ExitFunc >)
Move constructor.
exit_action(Func &&fn) noexcept(std::is_nothrow_constructible_v< ExitFunc, Func >||std::is_nothrow_constructible_v< ExitFunc, Func & >)
Constructs a new exit_action from an exit function of type Func.
~exit_action() noexcept
Calls the exit function if m_is_armed is active, then destroys the object.
void release() noexcept
Makes the exit_action object inactive.
A scope guard that calls its exit function when a scope is exited via an exception.
fail_action(fail_action &&other) noexcept(std::is_nothrow_move_constructible_v< ExitFunc >||std::is_nothrow_copy_constructible_v< ExitFunc >)
Move constructor.
fail_action(Func &&fn) noexcept(std::is_nothrow_constructible_v< ExitFunc, Func >||std::is_nothrow_constructible_v< ExitFunc, Func & >)
Constructs a new fail_action from an exit function of type Func.
void release() noexcept
Makes the fail_action object inactive.
fail_action(Func &&fn) noexcept
Constructs a new fail_action from an exit function of type Func.
~fail_action() noexcept
Calls the exit function if the scope is exited via an exception and destroys the object.
A scope guard that calls its exit function when a scope is exited normally.
success_action(Func &&fn) noexcept(std::is_nothrow_constructible_v< ExitFunc, Func >||std::is_nothrow_constructible_v< ExitFunc, Func & >)
Constructs a new success_action from an exit function of type Func.
~success_action() noexcept(noexcept(this->m_exit_function()))
Calls the exit function when the scope is exited normally if the success_action is active,...
success_action(success_action &&other) noexcept(std::is_nothrow_move_constructible_v< ExitFunc >||std::is_nothrow_copy_constructible_v< ExitFunc >)
Move constructor.
void release() noexcept
Makes the success_action object inactive.
success_action(Func &&fn) noexcept
Constructs a new success_action from an exit function of type Func.
success_action(ExitFunc) -> success_action< ExitFunc >
Deduction guide for success_action.
exit_action(ExitFunc) -> exit_action< ExitFunc >
Deduction guide for exit_action.
fail_action(ExitFunc) -> fail_action< ExitFunc >
Deduction guide for fail_action.