C++可变参数模板参数循环如何实现提前终止?
原来的数组初始化展开方式会在编译期把所有参数对应的ProcessInvoke调用全部展开,运行时会依次执行所有调用,无法提前终止。要实现提前终止,需要利用逻辑运算符的短路特性,或者模板递归的分支返回逻辑,以下是两种可落地的实现方案:
方案1:C++17及以上版本(折叠表达式实现,最简)
利用C++17引入的折叠表达式 + 逻辑或的短路求值特性:只要前面的表达式返回true,后续表达式就不会执行。
首先修改ProcessInvoke返回bool值,匹配成功时返回true:
template<class T> bool ProcessInvoke(const A &a) { std::cout << "Check Type " << T::ID << std::endl; if (a.GetID() == T::ID) { std::cout << "Process " << a.GetID() << " OK" << std::endl; return true; } return false; }
然后修改Process函数使用折叠表达式:
template<class...T> void Process(const A &a) { // 逻辑或短路:匹配到第一个返回true的调用后,不再执行后续参数的ProcessInvoke (ProcessInvoke<T>(a) || ...); }
方案2:C11/C14版本(递归模板实现)
如果编译环境不支持C++17,可以用模板递归+提前返回实现:
和上述方案一样先修改ProcessInvoke返回bool值,再新增递归处理的实现函数:
// 递归终止:参数包为空时无操作 void ProcessImpl(const A&) {} // 递归处理:先处理第一个参数,匹配成功直接返回,否则递归处理剩余参数 template <class First, class... Rest> void ProcessImpl(const A& a) { if (ProcessInvoke<First>(a)) { return; } ProcessImpl<Rest...>(a); } // 对外的Process接口转发到递归实现 template<class...T> void Process(const A &a) { ProcessImpl<T...>(a); }
效果验证
修改后执行Process<B1, B2, B3>(b1),输出仅为:
Check Type 1 Process 1 OK
不会再调用B2、B3对应的ProcessInvoke,符合提前终止的需求。
注意:匹配优先级和模板参数传入的顺序一致,会优先匹配排在前面的类型
内容的提问来源于stack exchange,提问作者Tao Li
相关产品推荐
相关产品推荐

