能否实现调用不同模板成员函数的for_each_type分发器?
问题解答
原代码无法编译的核心原因是:A::a和A::b是成员函数模板,而for_each_type的模板参数要求的是独立的类模板(template<typename> class Fn),两者类型完全不匹配——成员函数模板不能直接作为模板模板参数传递,也没法像类模板那样用Fn<char>()的方式实例化调用。
我们可以通过调整for_each_type的设计来实现需求,以下是几种可行方案:
方案1:用Lambda包装成员函数调用
修改for_each_type,让它接受一个可调用对象,内部针对每个目标类型调用该对象并传入当前实例:
struct A { template<typename T> void a() { /* 这里写a<T>的具体逻辑 */ } template<typename T> void b() { /* 这里写b<T>的具体逻辑 */ } template<typename F> void for_each_type(F&& func) { // 遍历目标类型序列,逐个调用传入的可调用对象 func.template operator()<char>(*this); func.template operator()<int>(*this); func.template operator()<float>(*this); // 可按需添加更多类型 } }; int main() { A obj; // 调用所有a<T> obj.for_each_type([]<typename T>(A& self) { self.template a<T>(); }); // 调用所有b<T>同理 obj.for_each_type([]<typename T>(A& self) { self.template b<T>(); }); }
方案2:用函数对象类封装成员函数
如果需要复用调用逻辑,可以定义专门的函数对象类,通过模板参数指定要调用的成员函数:
struct A { template<typename T> void a() { /* 实现 */ } template<typename T> void b() { /* 实现 */ } // 调整for_each_type,接受模板化的函数对象 template<template<typename> class FuncObj> void for_each_type() { FuncObj<char>{}(*this); FuncObj<int>{}(*this); FuncObj<float>{}(*this); } }; // 封装调用a<T>的函数对象 template<typename T> struct CallA { void operator()(A& obj) { obj.template a<T>(); } }; // 封装调用b<T>的函数对象 template<typename T> struct CallB { void operator()(A& obj) { obj.template b<T>(); } }; int main() { A obj; // 一次性调用所有a<T> obj.for_each_type<CallA>(); // 一次性调用所有b<T> obj.for_each_type<CallB>(); }
方案3:C++20+用概念简化(可选)
如果使用C++20及以上版本,可以用概念约束可调用对象,让代码更简洁清晰:
#include <concepts> struct A { template<typename T> void a() {} template<typename T> void b() {} template<std::invocable<A&, char> F> requires std::invocable<A&, int> && std::invocable<A&, float> void for_each_type(F&& func) { // 用类型标签传递目标类型 func(*this, char{}); func(*this, int{}); func(*this, float{}); } }; int main() { A obj; obj.for_each_type([](A& self, auto tag) { using T = decltype(tag); self.template a<T>(); }); }
核心思路总结:成员函数模板不能直接作为模板模板参数传递,必须通过Lambda、函数对象等可调用载体,把成员函数的调用逻辑包装起来,让for_each_type能遍历目标类型序列,逐个触发对应成员函数的调用。
内容的提问来源于stack exchange,提问作者user416983
相关产品推荐
相关产品推荐

