Created
March 31, 2025 17:57
-
-
Save jemand2001/177abb29b5a2c73bf30798b273553c8f to your computer and use it in GitHub Desktop.
event handling returning collected results of events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "signals.hpp" | |
| #include <iostream> | |
| struct MyEvent { | |
| using Signature = void(int); | |
| }; | |
| struct OtherEvent { | |
| using Signature = int(int); | |
| }; | |
| class Emitter1 : public EventEmitter<Emitter1, MyEvent> {}; | |
| class Emitter2 : public EventEmitter<Emitter2, OtherEvent> {}; | |
| template <int N> int add_n(int x) { return x + N; } | |
| int main() { | |
| Emitter1 e; | |
| auto log_number = [](int x) { std::cout << x << '\n'; }; | |
| e.add_event_listener<MyEvent>(log_number); | |
| e.emit<MyEvent>(12); | |
| Emitter2 e2; | |
| e2.add_event_listener<OtherEvent>(add_n<0>); | |
| e2.add_event_listener<OtherEvent>(add_n<1>); | |
| e2.add_event_listener<OtherEvent>(add_n<2>); | |
| e2.add_event_listener<OtherEvent>(add_n<3>); | |
| e2.add_event_listener<OtherEvent>(add_n<4>); | |
| auto x = e2.emit<OtherEvent>(1); | |
| for (int i : x) { | |
| std::cout << "e2 returned " << i << '\n'; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "traits.hpp" | |
| #include <concepts> | |
| #include <functional> | |
| #include <tuple> | |
| #include <type_traits> | |
| #include <vector> | |
| template <typename Fn, typename... Args> | |
| concept returns_void = std::invocable<Fn, Args...> && | |
| std::same_as<std::invoke_result_t<Fn, Args...>, void>; | |
| template <typename T> | |
| concept event_type = requires() { typename T::Signature; }; | |
| template <typename Me, event_type... Es> class EventEmitter; | |
| template <typename Me> class EventEmitter<Me> { | |
| static_assert(false, "must have at least one associated event!"); | |
| }; | |
| template <typename Me, event_type E, event_type... Es> | |
| class EventEmitter<Me, E, Es...> { | |
| static_assert(unique<E, Es...>, | |
| "this class can't work if you have multiple identical types " | |
| "of events"); | |
| template <typename S> using Fn = std::function<S>; | |
| std::tuple<std::vector<Fn<typename E::Signature>>, | |
| std::vector<Fn<typename Es::Signature>>...> | |
| handlers; | |
| public: | |
| template <one_of<E, Es...> ET> | |
| void add_event_listener(const Fn<typename ET::Signature> &fn) { | |
| std::get<std::vector<Fn<typename ET::Signature>>>(handlers).push_back(fn); | |
| } | |
| template <one_of<E, Es...> ET, typename... Args> | |
| void emit(Args &&...args) | |
| requires(returns_void<typename ET::Signature, Args...>) | |
| { | |
| for (auto &f : | |
| std::get<std::vector<Fn<typename ET::Signature>>>(handlers)) { | |
| f(args...); | |
| } | |
| } | |
| template <one_of<E, Es...> ET, typename... Args> | |
| auto emit(Args &&...args) | |
| requires(!returns_void<typename ET::Signature, Args...>) | |
| { | |
| using T = std::invoke_result_t<typename ET::Signature, Args...>; | |
| std::vector<T> v; | |
| for (auto &f : | |
| std::get<std::vector<Fn<typename ET::Signature>>>(handlers)) { | |
| v.push_back(f(args...)); | |
| } | |
| return v; | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <concepts> | |
| template <typename T, typename... Ts> struct is_one_of; | |
| template <typename T, typename... Ts> | |
| struct is_one_of<T, T, Ts...> : std::true_type {}; | |
| template <typename T> struct is_one_of<T> : std::false_type {}; | |
| template <typename T, typename R, typename... Ts> | |
| struct is_one_of<T, R, Ts...> : is_one_of<T, Ts...> {}; | |
| template <typename T, typename... Ts> | |
| concept one_of = is_one_of<T, Ts...>::value; | |
| template <typename...> struct is_unique; | |
| template <typename T> struct is_unique<T> : std::true_type {}; | |
| template <typename T, typename... Ts> struct is_unique<T, Ts...> { | |
| constexpr static bool value = | |
| (!std::same_as<T, Ts> && ... && is_unique<Ts...>::value); | |
| }; | |
| template <typename... Ts> | |
| concept unique = is_unique<Ts...>::value; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment