C++如何将成员函数指针作为类模板的模板参数使用?
C++成员函数指针类模板实现方案
问题结论
需求完全明确,该功能在C++11及更高标准中均可实现,编译报错是语法使用错误导致的。
报错原因
你在类模板的第二个非类型参数(成员函数指针)前错误添加了template<typename... Args>前缀,该语法仅用于声明模板模板参数,不能用来描述带可变参数的成员函数指针,因此编译器解析语法失败抛出错误。
正确实现
C++11兼容实现
C++11标准下可以通过类模板偏特化匹配任意参数列表的void返回成员函数:
#include <vector> #include <utility> // 前置声明 template<typename T, typename FuncType, FuncType func> class EngineSystem; // 偏特化匹配返回void的T类成员函数 template<typename T, typename... Args, void(T::*func)(Args...)> class EngineSystem<T, void(T::*)(Args...), func> { public: // 注册实例接口示例 void addHandler(T* instance) { handlers_.push_back(instance); } template<typename... FwdArgs> void update(FwdArgs&&... args) { for (T* handler : handlers_) { (handler->*func)(std::forward<FwdArgs>(args)...); } } private: std::vector<T*> handlers_; };
用法示例
#include <string> class TestClass { public: void doSomething(int a, const std::string& b) { // 自定义业务逻辑 } }; // 实例化类模板 EngineSystem<TestClass, decltype(&TestClass::doSomething), &TestClass::doSomething> system; // 使用流程:先注册实例,再调用update批量执行 TestClass ins1, ins2; system.addHandler(&ins1); system.addHandler(&ins2); system.update(10, "test"); // 会同时调用ins1和ins2的doSomething方法
C++17及以上简化实现
C++17引入auto非类型模板参数和std::invoke,可以大幅简化代码,不需要偏特化:
#include <vector> #include <utility> #include <functional> #include <type_traits> template<typename T, auto func> class EngineSystem { // 编译期校验参数合法性,不需要校验可直接删除本段 static_assert(std::is_member_function_pointer_v<decltype(func)>, "第二个模板参数必须是成员函数指针"); static_assert(std::is_void_v<typename std::function<std::remove_pointer_t<decltype(func)>>::result_type>, "传入的成员函数返回值必须为void"); public: void addHandler(T* instance) { handlers_.push_back(instance); } template<typename... FwdArgs> void update(FwdArgs&&... args) { for (T* handler : handlers_) { std::invoke(func, handler, std::forward<FwdArgs>(args)...); } } private: std::vector<T*> handlers_; };
用法示例
// 不需要额外传函数类型,写法更简洁 EngineSystem<TestClass, &TestClass::doSomething> system;
内容的提问来源于stack exchange,提问作者JensB
相关产品推荐
相关产品推荐

