C++是否可以指定成员函数类型的模板参数包?
问题解答
该需求可以实现,且不需要你额外将用到的函数封装到结构体中。你给出的模板定义语法本身符合C++标准,无法正常运行通常是参数包展开逻辑或者调用方式有误导致。
正确实现示例
基础实现(C++17及以上,代码最简洁)
#include <iostream> // 测试用的业务类,不需要对成员函数做额外封装 struct TestBiz { void func1() { std::cout << "执行func1\n"; } void func2() { std::cout << "执行func2\n"; } void func3() { std::cout << "执行func3\n"; } }; // 成员函数指针模板参数包的实现,用折叠表达式展开参数包 template <typename T, void (T::*Func)()...> void application(T& obj) { // 依次调用所有传入的成员函数 ((obj.*Func)(), ...); } int main() { TestBiz obj; // 调用时直接传入类名+成员函数指针即可 application<TestBiz, &TestBiz::func1, &TestBiz::func2, &TestBiz::func3>(obj); return 0; }
兼容C++11/14的实现
如果使用的标准不支持折叠表达式,可以用初始化列表完成参数包展开:
template <typename T, void (T::*Func)()...> void application(T& obj) { using swallow = int[]; // 初始化列表兜底实现参数包展开,(void)是为了规避未使用变量的编译警告 (void)swallow{1, ((obj.*Func)(), 0)...}; }
常见报错原因
- 调用时未对成员函数显式取地址:非静态成员函数指针必须使用
&类名::函数名的形式传入,无法像普通函数一样隐式转换为指针 - 成员函数签名不匹配:如果传入的成员函数带有const/volatile限定符、参数数量/类型不匹配、返回值不同,都会触发编译错误。C++17及以上版本可以把非类型模板参数改为
auto自动推导签名,适配任意符合要求的成员函数:template <typename T, auto... Funcs> void application(T& obj) { ((obj.*Funcs)(), ...); } - 未正确处理参数包展开:如果使用C++11/14标准,不能直接用折叠表达式,需要用初始化列表等语法完成参数包展开
内容的提问来源于stack exchange,提问作者Jonas Hjulstad
相关产品推荐
相关产品推荐

