@@ -66,12 +66,17 @@ concept HasStaticRelease = requires {
6666 { T::release () } -> std::same_as<void >;
6767};
6868
69+ template <typename T>
70+ concept HasInvokeOnConstructorExceptionBool = requires {
71+ { T::invoke_on_constructor_exception } -> std::convertible_to<const bool >;
72+ };
73+
6974template <typename F, typename R, typename ... Args>
7075concept invocable_return = std::invocable<F, Args...> && std::convertible_to<std::invoke_result_t <F, Args...>, R>;
7176
7277template <typename F>
7378concept scope_exit_function =
74- invocable_return<F, void > && std::is_nothrow_move_constructible_v<F> && std::is_copy_constructible_v<F>;
79+ invocable_return<F, void > && ( std::is_nothrow_move_constructible_v<F> || std::is_copy_constructible_v<F>) ;
7580
7681template <typename T>
7782concept scope_invoke_checker = HasStaticCanInvoke<T> || HasCanInvoke<T> || invocable_return<T, bool >;
@@ -82,17 +87,24 @@ struct ExecuteAlways;
8287
8388// =========================================================
8489
85-
8690template <scope_exit_function ScopeExitFunc, scope_invoke_checker InvokeChecker = ExecuteAlways>
8791class scope_guard {
8892 public:
89- explicit constexpr scope_guard (ScopeExitFunc&& exit_func) noexcept (
90- std::is_nothrow_constructible_v<ScopeExitFunc>) try
93+ explicit constexpr scope_guard (ScopeExitFunc&& exit_func) //
94+ noexcept (std::is_nothrow_constructible_v<ScopeExitFunc>)
95+ requires !std::is_same_v<decltype(exit_func), scope_guard>
96+ try
9197 : m_exit_func(std::forward<ScopeExitFunc>(exit_func)) //
9298 {
9399 } catch (...) {
94- if constexpr (InvokeChecker::invoke_on_constructor_exception) {
95- exit_func ();
100+ if constexpr (!std::is_nothrow_constructible_v<ScopeExitFunc>) {
101+ if constexpr (HasInvokeOnConstructorExceptionBool<ScopeExitFunc>) {
102+ if (InvokeChecker::invoke_on_constructor_exception) {
103+ exit_func ();
104+ }
105+ }
106+
107+ throw ;
96108 }
97109 }
98110
0 commit comments