You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化EnTT事件注册:通过函数指针推导事件类型

简化EnTT事件注册的实现方案

完全可以实现你想要的简化写法,核心是通过模板元编程从函数指针里自动提取事件类型,不用手动指定Event模板参数。下面是具体实现步骤和代码:

核心思路

利用模板推导机制,编写辅助模板解析函数指针的签名,提取出其中的事件参数类型,再自动调用EnTT的sink和connect接口。

具体实现

1. 编写类型提取辅助模板

这个模板负责从函数指针中提取事件类型(假设函数的第一个参数就是事件类型):

// 基础模板,用于匹配不同函数签名
template<typename Func>
struct EventTypeFromFunc;

// 特化:匹配普通函数(参数为const Event&)
template<typename Event>
struct EventTypeFromFunc<void(*)(const Event&)> {
    using type = Event;
};

// 特化:匹配类成员函数(参数为const Event&)
template<typename Class, typename Event>
struct EventTypeFromFunc<void(Class::*)(const Event&)> {
    using type = Event;
};

// 别名模板,简化类型提取的写法
template<typename Func>
using EventTypeFromFunc_t = typename EventTypeFromFunc<Func>::type;

2. 实现简化的registerEvent函数

基于上面的类型提取模板,写出两种调用方式的函数:

方式一:运行时传入函数指针

#include <entt/entt.hpp>

template<typename Func>
void registerEvent(entt::dispatcher& dispatcher, Func func) {
    // 自动提取事件类型
    using Event = EventTypeFromFunc_t<Func>;
    dispatcher.sink<Event>().connect(func);
}

方式二:编译期指定函数指针(模板参数形式)

template<auto Func>
void registerEvent(entt::dispatcher& dispatcher) {
    using Event = EventTypeFromFunc_t<decltype(Func)>;
    dispatcher.sink<Event>().connect<Func>();
}

使用示例

// 定义事件类型
struct MyEvent {};
struct AnotherEvent {};

// 普通事件处理函数
void OnMyEvent(const MyEvent&) {
    // 处理逻辑
}

// 类成员事件处理函数
class MySystem {
public:
    void OnAnotherEvent(const AnotherEvent&) {
        // 处理逻辑
    }
};

int main() {
    entt::dispatcher dispatcher;
    MySystem system;

    // 调用方式1:传入函数指针
    registerEvent(dispatcher, &OnMyEvent);

    // 调用方式2:模板参数指定函数指针
    registerEvent<&OnMyEvent>(dispatcher);

    // 成员函数的注册(需要绑定实例)
    registerEvent(dispatcher, std::bind(&MySystem::OnAnotherEvent, &system));
    // 或者扩展成员函数专用版本(见下方补充)
}

补充:成员函数直接注册的扩展

如果想更简洁地注册成员函数,可以添加重载:

template<typename Class, typename Event>
void registerEvent(entt::dispatcher& dispatcher, void(Class::*func)(const Event&), Class* instance) {
    dispatcher.sink<Event>().connect(func, instance);
}

// 使用示例
registerEvent(dispatcher, &MySystem::OnAnotherEvent, &system);

注意事项

  • 如果你的事件处理函数参数不是const Event&(比如值传递、非const引用),需要对应修改EventTypeFromFunc的特化模板,匹配对应的函数签名。
  • 确保EnTT版本支持你使用的connect重载,不同版本的EnTT在接口细节上可能略有差异。

内容的提问来源于stack exchange,提问作者confused cmake user

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:43:30