Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
scope_guard.hpp
Go to the documentation of this file.
1// Copyright 2024, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_SCOPE_GUARD_SCOPE_GUARD_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_SCOPE_GUARD_SCOPE_GUARD_HPP_
7
8// IWYU pragma: private, include "arene/base/scope_guard.hpp"
9// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
10
11// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
12#include "arene/base/compiler_support/attributes.hpp"
13#include "arene/base/constraints/constraints.hpp"
14#include "arene/base/stdlib_choice/enable_if.hpp"
15#include "arene/base/stdlib_choice/exchange.hpp"
16#include "arene/base/stdlib_choice/forward.hpp"
17#include "arene/base/stdlib_choice/is_constructible.hpp"
18#include "arene/base/stdlib_choice/is_move_constructible.hpp"
19#include "arene/base/stdlib_choice/is_same.hpp"
20#include "arene/base/stdlib_choice/move.hpp"
21#include "arene/base/stdlib_choice/remove_cv.hpp"
22#include "arene/base/stdlib_choice/remove_reference.hpp"
23#include "arene/base/type_traits/is_invocable.hpp"
24#include "arene/base/type_traits/remove_cvref.hpp"
25// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
26
27// parasoft-begin-suppress CERT_C-EXP37-a-3 "False positive: The rule does not mention naming all parameters"
28
29namespace arene {
30namespace base {
31
32/// @brief RAII utility for executing logic on scope exit
33///
34/// The @c scope_guard type is a utility that helps writing exception-safe code by ensuring that some code gets run on
35/// scope-exit, regardless of how the scope is exited (return, exception, flowing off end, etc). The destructor of the
36/// @c scope_guard class invokes the function passed to the constructor.
37///
38/// @see arene::base::on_scope_exit for a helper function for creating @c scope_guard instances.
39///
40/// @tparam Func The functor to be called on scope exit. Must have signature <c> void(void) noexcept </c>. It also must
41/// be nothrow move constructable for scope_guard to be move-constructable.
42template <typename Func>
43class ARENE_NODISCARD scope_guard {
44 static_assert(is_nothrow_invocable_r_v<void, Func>, "Func must have signature void(void) noexcept");
45
46 public:
47 /// @brief Construct a new scope_guard that decay-copies the
48 /// function and ensure that it is called upon destruction of the
49 /// scope_guard object.
50 /// @tparam Func2 The type of the supplied callable
51 /// @param supplied_callable The supplied callable
52 template <
53 typename Func2,
57 // This has been guarded against by the !is_same<...> constraint above.
58 // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)
62
63 /// @brief Move constructor.
64 ///
65 /// Moves ownership of the function and responsibility for calling the function on destruction to the newly
66 /// constructed scope_guard object.
67 ///
68 /// @param other The scope_guard to move from.
69 /// @post The held function will be the one from @c other
70 /// @post The cancel state will be the one from @c other
71 /// @post The moved-from @c scope_guard can be safely destructed.
75 static_assert(std::is_nothrow_move_constructible<Func>::value, "Func must be nothrow move constructible");
76 }
77
78 /// @brief Move assignment is deleted as allowing it would overwrite the existing guard function without executing it.
79 auto operator=(scope_guard&& other) -> scope_guard& = delete;
80
81 /// @brief copy-construction is deleted as two guards cannot own the same function.
82 scope_guard(scope_guard const&) = delete;
83 /// @brief copy-assignment is deleted as two guards cannot own the same function.
84 auto operator=(scope_guard const&) -> scope_guard& = delete;
85
86 /// @brief Destroy the scope guard and invoke the function if it should be executed
87 /// @post The held function is executed as if via @c invoke_now() .
89
90 /// @brief Declares the held function should not be invoked.
91 /// @post Calls to @c invoke_now() will be noops.
92 void cancel() noexcept { cancelled_ = true; }
93
94 /// @brief Invokes the held function if it has not be otherwise canceled.
95 /// @post If @c cancel() has not been called, invokes the held functor.
96 /// @post Subsequent calls to @c invoke_now() are noops as if @c cancel() had been called.
97 void invoke_now() noexcept {
98 if (!cancelled_) {
99 cancelled_ = true;
100 func_();
101 }
102 }
103
104 private:
105 /// @brief The function to invoke
106 Func func_;
107
108 /// @brief Flag to signal if the functor should be invoked.
109 bool cancelled_; // NOLINT(modernize-use-default-member-init)
110};
111
112/// @brief Declarative helper for constructing @c scope_guard instances.
113///
114/// A simple factory function for @c scope_guard with a declarative name that makes its purpose clear. Example usage:
115/// \snippet docs/examples/scope_guard_examples.cpp basic_usage
116///
117/// @tparam CallableType a callable with signature <c> void(void) noexcept </c>. Must be move-copyable and decay
118/// constructible.
119/// @param func The callable to invoke upon destruction of the returned scope_guard object.
120/// @return scope_guard A scope_guard instance initialized from @c func through forwarding.
121template <typename CallableType, constraints<std::enable_if_t<is_nothrow_invocable_r_v<void, CallableType>>> = nullptr>
127
128} // namespace base
129} // namespace arene
130#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_SCOPE_GUARD_SCOPE_GUARD_HPP_
RAII utility for executing logic on scope exit.
Definition scope_guard.hpp:43
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10