header_utils
Loading...
Searching...
No Matches
functional.h
1
4
5#pragma once
6
7#include <functional>
8#include <optional>
9#include <utility>
10#include <map>
11#include <ranges>
12
13// Shamelessly stolen from https://github.com/klmr/multifunction
14namespace ghassanpl
15{
18
19 template <typename R, typename... ARGS>
20 struct multicast_function_traits
21 {
22 using return_type = R;
23 using argument_types = std::tuple<ARGS...>;
24 };
25
26 template <typename R, typename ARG>
27 struct multicast_function_traits<R, ARG>
28 {
29 using return_type = R;
30 using argument_type = ARG;
31 };
32
33 template <typename R, typename ARG1, typename ARG2>
34 struct multicast_function_traits<R, ARG1, ARG2>
35 {
36 using return_type = R;
37 using first_argument_type = ARG1;
38 using second_argument_type = ARG2;
39 };
40
41
42 template <typename R, typename... ARGS>
43 class mutlticast_function;
44
47 template <typename R, typename... ARGS>
48 class mutlticast_function<R(ARGS...)> : public multicast_function_traits<R, ARGS...>
49 {
50 public:
51
52 enum class handle : size_t {};
53
54 mutlticast_function() noexcept = default;
55 mutlticast_function(mutlticast_function const&) noexcept = default;
56 mutlticast_function(mutlticast_function&&) noexcept = default;
57 mutlticast_function& operator =(mutlticast_function const&) noexcept = default;
58 mutlticast_function& operator =(mutlticast_function&&) noexcept = default;
59
62 template <typename F>
63 handle operator+=(F&& listener) { return add(std::forward<F>(listener)); }
64
67 template <typename F>
68 handle add(F&& listener)
69 {
70 const auto new_id = handle{ m_last_id++ };
71 m_listeners.emplace(new_id, std::forward<F>(listener));
72 return new_id;
73 }
74
76 void operator-=(handle handle) { remove(handle); }
77
79 void remove(handle handle)
80 {
81 m_listeners.erase(handle);
82 }
83
87 template <typename... CALL_ARGS>
88 auto operator()(CALL_ARGS&&... args) const
89 {
90 return call_helper<R>::template call(m_listeners, std::forward<CALL_ARGS>(args)...);
91 }
92
94 void clear()
95 {
96 m_listeners.clear();
97 }
98
100 auto listeners() const { return std::ranges::views::values(m_listeners); }
101
102 private:
103
104 template <typename R>
105 struct call_helper
106 {
107 template <typename... CALL_ARGS>
108 static std::vector<R> call(std::map<handle, std::function<R(ARGS...)>> const& listeners, CALL_ARGS&&... args)
109 {
110 std::vector<R> ret;
111 ret.reserve(listeners.size());
112 for (auto& [handle, listener] : listeners)
113 ret.push_back(listener(std::forward<CALL_ARGS>(args)...));
114 return ret;
115 }
116 };
117
118 template <>
119 struct call_helper<void>
120 {
121 template <typename... CALL_ARGS>
122 static void call(std::map<handle, std::function<void(ARGS...)>> const& listeners, CALL_ARGS&&... args)
123 {
124 for (auto& [handle, listener] : listeners)
125 listener(std::forward<CALL_ARGS>(args)...);
126 }
127 };
128
129 std::map<handle, std::function<R(ARGS...)>> m_listeners;
130 size_t m_last_id = {};
131 };
132
135 template <typename... ARGS>
136 auto make_single_time_function(std::function<void(ARGS...)> func)
137 {
138 return [func = std::move(func)]<typename... CALL_ARGS>(CALL_ARGS&&... args) mutable {
139 if (func) std::exchange(func, {})(std::forward<CALL_ARGS>(args)...);
140 };
141 }
142
145 template <typename FUNC>
147 {
148 return make_single_time_function(std::function{ std::forward<FUNC>(func) });
149 }
150
152 template <typename T, typename FUNC>
153 auto transform(std::optional<T> const& value, FUNC&& func) -> decltype(std::optional{ func(value.value()) })
154 {
155 return value ? std::optional{ func(value.value()) } : std::nullopt;
156 }
157
158} // namespace util
auto listeners() const
Returns a view over all the added invocables.
Definition functional.h:100
void clear()
Removes all the invocables from this objects.
Definition functional.h:94
void remove(handle handle)
Removes the invocable associated with handle
Definition functional.h:79
handle add(F &&listener)
Adds a new invocable to the list.
Definition functional.h:68
auto operator()(CALL_ARGS &&... args) const
Calls all the invocables added to this object.
Definition functional.h:88
constexpr auto bit_count
Equal to the number of bits in the type.
Definition bits.h:33
auto make_single_time_function(std::function< void(ARGS...)> func)
Returns a function that calls func when invoked, but only the first time.
Definition functional.h:136
Primary namespace for everything in this library.
Definition align+rec2.h:10