- explicit ScopeGuardImpl(const FunctionType& fn)
- : function_(fn) {}
-
- explicit ScopeGuardImpl(FunctionType&& fn)
- : function_(std::move(fn)) {}
-
- ScopeGuardImpl(ScopeGuardImpl&& other)
- : ScopeGuardImplBase(std::move(other))
- , function_(std::move(other.function_)) {
+ explicit ScopeGuardImpl(FunctionType& fn) noexcept(
+ std::is_nothrow_copy_constructible<FunctionType>::value)
+ : ScopeGuardImpl(
+ asConst(fn),
+ makeFailsafe(std::is_nothrow_copy_constructible<FunctionType>{},
+ &fn)) {}
+
+ explicit ScopeGuardImpl(const FunctionType& fn) noexcept(
+ std::is_nothrow_copy_constructible<FunctionType>::value)
+ : ScopeGuardImpl(
+ fn,
+ makeFailsafe(std::is_nothrow_copy_constructible<FunctionType>{},
+ &fn)) {}
+
+ explicit ScopeGuardImpl(FunctionType&& fn) noexcept(
+ std::is_nothrow_move_constructible<FunctionType>::value)
+ : ScopeGuardImpl(
+ std::move_if_noexcept(fn),
+ makeFailsafe(std::is_nothrow_move_constructible<FunctionType>{},
+ &fn)) {}
+
+ ScopeGuardImpl(ScopeGuardImpl&& other) noexcept(
+ std::is_nothrow_move_constructible<FunctionType>::value)
+ : function_(std::move_if_noexcept(other.function_)) {
+ // If the above line attempts a copy and the copy throws, other is
+ // left owning the cleanup action and will execute it (or not) depending
+ // on the value of other.dismissed_. The following lines only execute
+ // if the move/copy succeeded, in which case *this assumes ownership of
+ // the cleanup action and dismisses other.
+ dismissed_ = other.dismissed_;
+ other.dismissed_ = true;