C++模板化事件系统中如何实现参数预绑定?
游戏引擎事件系统的参数预绑定实现
我的游戏引擎包含一套事件系统,核心组件为Event与EventCallback,原有实现如下:
原有事件系统代码
Event.h
#ifndef _EVENT_H_ #define _EVENT_H_ #include "EventCallback.h" #include <vector> template<typename... Args> class Event { public: Event() = default; ~Event() { for (IEventCallback<Args...>* action : m_actions) delete action; m_actions.clear(); } void AddListener(IEventCallback<Args...>* action) { m_actions.push_back(action); } void RemoveListener(IEventCallback<Args...>* action) { auto position = std::find(m_actions.begin(), m_actions.end(), action); if (position == m_actions.end()) return; m_actions.erase(position); if(action != nullptr) delete action; } void Trigger(Args... args) { for (IEventCallback<Args...>* action : m_actions) { action->Trigger(args...); } } private: std::vector<IEventCallback<Args...>*> m_actions; }; #endif
EventCallback.h
#ifndef _EVENTCALLBACK_H_ #define _EVENTCALLBACK_H_ template<typename... Args> class IEventCallback { public: virtual bool operator == (IEventCallback* other) = 0; virtual void Trigger(Args... args) = 0; }; template<typename T, typename... Args> class EventCallback : public IEventCallback<Args...> { public: EventCallback(T* instance, void (T::* function)(Args... args)) { m_instance = instance; m_function = function; } virtual void Trigger(Args... args) override { if(m_instance != nullptr) (m_instance->*m_function)(args...); } virtual bool operator == (IEventCallback<Args...>* other) override { EventCallback<T, Args...>* otherEventCallback = dynamic_cast<EventCallback<T, Args...>*>(other); if (otherEventCallback == nullptr) return false; return (this->m_function == otherEventCallback->m_function) && (this->m_instance == otherEventCallback->m_instance); } private: void (T::*m_function)(Args...); T* m_instance; }; #endif
当前使用方式
目前可以按以下方式创建事件并添加监听器:
CameraController* instance = new CameraController(); Event<InputCallbackData> Ongoing; Ongoing.AddListener(new EventCallback<CameraController, InputCallbackData>(this, &CameraController::MoveRight)); void CameraController::MoveRight(InputCallbackData data) { Vector3D cameraPos = m_cameraComponent->GetWorldPosition(); Vector3D cameraRight = m_cameraComponent->GetWorldRotation().GetRightDirection(); m_cameraComponent->SetWorldPosition(cameraPos + cameraRight * movementSpeed); } InputCallbackData inputCallbackData = InputCallbackData(); Ongoing.Trigger(inputCallbackData);
需求:实现参数预绑定
希望为EventCallback添加参数预绑定功能,预期用法如下:
CameraController* instance = new CameraController(); Event<InputCallbackData> Ongoing; Ongoing.AddListener(new EventCallback<CameraController, InputCallbackData>(this, &CameraController::MoveRight, 10)); void CameraController::MoveRight(InputCallbackData data, float speed) { Vector3D cameraPos = m_cameraComponent->GetWorldPosition(); Vector3D cameraRight = m_cameraComponent->GetWorldRotation().GetRightDirection(); m_cameraComponent->SetWorldPosition(cameraPos + cameraRight * speed); } InputCallbackData inputCallbackData = InputCallbackData(); Ongoing.Trigger(inputCallbackData);
解决方案
修改后的EventCallback.h代码如下:
#ifndef _EVENTCALLBACK_H_ #define _EVENTCALLBACK_H_ #include <functional> template<typename... Args> class ICallback { public: virtual void Call(Args... args) = 0; }; template<typename... Args> class IEventCallback { public: virtual bool operator == (IEventCallback* other) = 0; virtual void Trigger(Args... args) = 0; }; template<typename T, typename... Args> class EventCallback : public IEventCallback<Args...> { public: template <typename... ExtraArgs> EventCallback(T* instance, void (T::*function)(Args..., ExtraArgs...), const ExtraArgs&... extra_args) { class MethodWrapper : public ICallback<Args...> { public: MethodWrapper(T* instance, void (T::* function)(Args..., ExtraArgs...), const ExtraArgs&... extra_args) : m_instance(instance), m_function(function), m_extra_args(std::make_tuple(extra_args...)) {} virtual void Call(Args... args) override { // 将元组展开为可变参数模板函数的参数 std::apply([&](const ExtraArgs&... extra_args) { (m_instance->*m_function)(args..., extra_args...); }, m_extra_args); } private: T* m_instance; void (T::* m_function)(Args... args, ExtraArgs...); std::tuple<ExtraArgs...> m_extra_args; }; m_callback = std::make_unique<MethodWrapper>(instance, function, extra_args...); } virtual void Trigger(Args... args) override { m_callback->Call(args...); } virtual bool operator == (IEventCallback<Args...>* other) override { EventCallback<T, Args...>* otherEventCallback = dynamic_cast<EventCallback<T, Args...>*>(other); return otherEventCallback->m_callback == m_callback; } private: std::unique_ptr<ICallback<Args...>> m_callback; }; #endif
内容的提问来源于stack exchange,提问作者mar ben
相关产品推荐
相关产品推荐

