diff options
author | crupest <crupest@outlook.com> | 2019-06-14 00:44:14 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-06-14 00:44:14 +0800 |
commit | 5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784 (patch) | |
tree | 970188397f236715d3d021ddcfcbdeeee73ee860 /include/cru/common/event.hpp | |
parent | 7b1e9fd2410c9d4fafbe5de9459b18775e6cc465 (diff) | |
download | cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.tar.gz cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.tar.bz2 cru-5ec370e5f91ad8b5ed7717eb93f4e3240ea4e784.zip |
...
Diffstat (limited to 'include/cru/common/event.hpp')
-rw-r--r-- | include/cru/common/event.hpp | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp index d8a24330..af282c30 100644 --- a/include/cru/common/event.hpp +++ b/include/cru/common/event.hpp @@ -79,13 +79,44 @@ inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { return EventRevoker(resolver_, token); } +template <typename TRaw> +using DeducedEventArgs = std::conditional_t< + std::is_lvalue_reference_v<TRaw>, TRaw, + std::conditional_t<std::is_scalar_v<TRaw>, TRaw, const TRaw&>>; + +// Provides an interface of event. +// +// Note that this class does not inherit Interface because Interface is +// public destructable, but I want to make this class not public +// destructable to prevent user from destructing it. +// +// IEvent only allow to add handler but not to raise the event. You may +// want to create an Event object and expose IEvent only so users won't +// be able to emit the event. +template <typename TEventArgs> +struct IEvent { + public: + using EventArgs = DeducedEventArgs<TEventArgs>; + using EventHandler = std::function<void(EventArgs)>; + + protected: + IEvent() = default; + IEvent(const IEvent& other) = delete; + IEvent(IEvent&& other) = delete; + IEvent& operator=(const IEvent& other) = delete; + IEvent& operator=(IEvent&& other) = delete; + ~IEvent() = default; + + public: + virtual EventRevoker AddHandler(const EventHandler& handler) = 0; + virtual EventRevoker AddHandler(EventHandler&& handler) = 0; +}; + // A non-copyable non-movable Event class. // It stores a list of event handlers. -template <typename... TArgs> -class Event : public details::EventBase { +template <typename TEventArgs> +class Event : public details::EventBase, public IEvent<TEventArgs> { public: - using EventHandler = std::function<void(TArgs...)>; - Event() = default; Event(const Event&) = delete; Event& operator=(const Event&) = delete; @@ -93,36 +124,26 @@ class Event : public details::EventBase { Event& operator=(Event&&) = delete; ~Event() = default; - EventRevoker AddHandler(const EventHandler& handler) { + EventRevoker AddHandler(const EventHandler& handler) override { const auto token = current_token_++; handlers_.emplace(token, handler); return CreateRevoker(token); } - EventRevoker AddHandler(EventHandler&& handler) { + EventRevoker AddHandler(EventHandler&& handler) override { const auto token = current_token_++; handlers_.emplace(token, std::move(handler)); return CreateRevoker(token); } - template <typename FArg> - EventRevoker AddHandler(FArg&& handler) { - static_assert(std::is_invocable_v<FArg, TArgs...>, - "Handler not invocable."); - const auto token = current_token_++; - handlers_.emplace(token, EventHandler(std::forward<FArg>(handler))); - return CreateRevoker(token); - } - - template <typename... FArg> - void Raise(FArg&&... args) { + void Raise(EventArgs args) { // copy the handlers to a list, because the handler might be removed // during executing, and the handler with its data will be destroyed. // if the handler is a lambda with member data, then the member data // will be destroyed and result in seg fault. std::list<EventHandler> handlers; for (const auto& [key, handler] : handlers_) handlers.push_back(handler); - for (const auto& handler : handlers) handler(std::forward<FArg>(args)...); + for (const auto& handler : handlers) handler(args); } protected: |