Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
defer.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <concepts>
7#include <type_traits>
8#include <utility>
9
10namespace helios::utils {
11
12/**
13 * @brief A utility class that defers the execution of a callable until the
14 * object goes out of scope.
15 * @tparam F The type of the callable to be executed upon destruction.
16 *
17 * @code
18 * // Pattern 1: Pre-defined lambda
19 * auto cleanup = [resource]() { delete resource; };
20 * HELIOS_DEFER_CALL(cleanup);
21 *
22 * // Pattern 2: Inline lambda (no capture list needed)
23 * HELIOS_DEFER {
24 * delete resource;
25 * };
26 * @endcode
27 */
28template <std::invocable F>
29class Defer {
30public:
31 Defer() = delete;
32
33 /**
34 * @brief Constructs a Defer object that will execute the provided callable
35 * upon destruction.
36 * @param func The callable to be executed.
37 */
38 constexpr explicit Defer(F func) noexcept(
39 std::is_nothrow_move_constructible_v<F>)
40 : func_(std::move(func)) {}
41 Defer(Defer&&) = delete;
42 Defer(const Defer&) = delete;
43 constexpr ~Defer() noexcept(std::is_nothrow_invocable_v<F>) { func_(); }
44
45 Defer& operator=(const Defer&) = delete;
46 Defer& operator=(Defer&&) = delete;
47
48private:
49 F func_;
50};
51
52namespace details {
53
54/// @brief Helper struct for the `HELIOS_DEFER` macro to enable inline lambda
55/// syntax.
57 template <std::invocable F>
58 constexpr auto operator+(F&& func) noexcept(
59 std::is_nothrow_constructible_v<Defer<std::remove_cvref_t<F>>, F>)
60 -> Defer<std::remove_cvref_t<F>> {
61 return Defer<std::remove_cvref_t<F>>(std::forward<F>(func));
62 }
63};
64
65} // namespace details
66
67} // namespace helios::utils
68
69/**
70 * @brief Defers execution of an inline lambda until the end of the current
71 * scope.
72 * @details The lambda is written directly after the macro without explicit
73 * capture list.
74 *
75 * @code
76 * int* ptr = new int(42);
77 * HELIOS_DEFER {
78 * delete ptr;
79 * };
80 * @endcode
81 */
82#define HELIOS_DEFER \
83 const auto HELIOS_CONCAT(_defer_, __COUNTER__) = \
84 ::helios::utils::details::DeferHelper() + [&] HELIOS_ALWAYS_INLINE()
85
86// NOLINTBEGIN(cppcoreguidelines-macro-usage)
87
88/**
89 * @brief Defers execution of a callable until the end of the current scope.
90 * @details Accepts lambdas, functors, function pointers, and `std::function`
91 * objects.
92 *
93 * @code
94 * auto cleanup = []() { std::cout << "Cleanup\n"; };
95 * HELIOS_DEFER_CALL(cleanup);
96 * @endcode
97 */
98#define HELIOS_DEFER_CALL(callable) \
99 const auto HELIOS_CONCAT(_defer_, __COUNTER__) = \
100 ::helios::utils::Defer(callable)
101
102// NOLINTEND(cppcoreguidelines-macro-usage)
A utility class that defers the execution of a callable until the object goes out of scope.
Definition defer.hpp:29
Defer & operator=(const Defer &)=delete
constexpr Defer(F func) noexcept(std::is_nothrow_move_constructible_v< F >)
Constructs a Defer object that will execute the provided callable upon destruction.
Definition defer.hpp:38
Defer(const Defer &)=delete
constexpr ~Defer() noexcept(std::is_nothrow_invocable_v< F >)
Definition defer.hpp:43
Defer(Defer &&)=delete
Defer & operator=(Defer &&)=delete
STL namespace.
Helper struct for the HELIOS_DEFER macro to enable inline lambda syntax.
Definition defer.hpp:56
constexpr auto operator+(F &&func) noexcept(std::is_nothrow_constructible_v< Defer< std::remove_cvref_t< F > >, F >) -> Defer< std::remove_cvref_t< F > >
Definition defer.hpp:58