#pragma once #include #include #include #include #include #include namespace cru { template class EventContext { public: EventContext() : argument_(), result_() {} explicit EventContext(TArgument argument) : argument_(std::move(argument)), result_() {} EventContext(TArgument argument, TResult result) : argument_(std::move(argument)), result_(std::move(result)) {} TArgument& GetArgument() { return argument_; } const TArgument& GetArgument() const { return argument_; } TResult& GetResult() { return result_; } const TResult& GetResult() const { return result_; } void SetResult(TResult&& result) { result_ = std::forward(result); } bool GetStopHandling() const { return stop_handling_; } void SetStopHandling(bool stop = true) { stop_handling_ = stop; } private: TArgument argument_; TResult result_; bool stop_handling_ = false; }; template class Event2; template constexpr bool is_event2_v = false; template constexpr bool is_event2_v> = true; template class EventHandlerToken { static_assert(is_event2_v, "TEvent2 must be Event2 class."); public: EventHandlerToken(ObjectResolver event_resolver, int token_value); ObjectResolver GetEventResolver() const { return event_resolver_; } int GetTokenValue() const { return token_value_; } void RevokeHandler() const; private: ObjectResolver event_resolver_; int token_value_; }; template class Event2 : public SelfResolvable> { public: using HandlerToken = EventHandlerToken; using Context = EventContext; using Handler = std::function; using SpyOnlyHandler = std::function; template static std::enable_if_t, Handler> WrapAsHandler( TFunc&& handler) { return Handler([h = std::forward(handler)](Context&) { h(); }); } template static std::enable_if_t, Handler> WrapAsHandler(TFunc&& handler) { return Handler(std::forward(handler)); } private: struct HandlerData { int token_value_; Handler handler_; }; public: Event2(const Event2&) = delete; Event2(Event2&&) = delete; Event2& operator=(const Event2&) = delete; Event2& operator=(Event2&&) = delete; ~Event2() override = default; public: void RevokeHandler(int token_value); void RevokeHandler(const HandlerToken& token) { return RevokeHandler(token.GetTokenValue()); } private: int current_token_value_ = 1; std::vector handlers_; }; template void EventHandlerToken::RevokeHandler() const { auto event = this->event_resolver_.Resolve(); if (event) { event->RevokeHandler(this->token_value_); } } } // namespace cru