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