C++参数包场景下如何从已知入参生成实参调用变参函数
C++变参模板按索引传参实现方案
核心需求
在func1中调用func时,按照模板参数包Cs的元素个数,依次传入入参s的s[0]、s[1]……对应索引位置的元素,两个函数共用同一参数包Cs。
实现代码
C++17及以上版本(最简实现)
利用C++17泛型lambda配合标准库std::index_sequence(需包含<utility>头文件),无需额外辅助函数即可完成展开:
#include <utility> template<class... Cs> void func(Cs... cs){ // 自定义业务逻辑 } template<class T, class... Cs> void func1(T s){ // 生成与Cs包长度一致的0起始索引序列,展开后取对应下标的s元素 [&]<std::size_t... Idx>(std::index_sequence<Idx...>) { func<Cs...>(s[Idx]...); }(std::make_index_sequence<sizeof...(Cs)>{}); } int main(){ char s[]="HI THERE!"; // 实际传入func的参数为s[0]='H'、s[1]='I'、s[2]=' ' func1<char*, char, char, char>(s); return 0; }
C11/C14兼容版本
旧标准不支持泛型lambda,需要额外实现一个辅助转发函数承接索引序列的展开逻辑:
#include <utility> template<class... Cs> void func(Cs... cs){ // 自定义业务逻辑 } // 辅助转发函数,额外接收索引序列参数包 template<class T, class... Cs, std::size_t... Idx> void func_helper(T s, std::index_sequence<Idx...>) { func<Cs...>(s[Idx]...); } template<class T, class... Cs> void func1(T s){ func_helper<T, Cs...>(s, std::make_index_sequence<sizeof...(Cs)>{}); } int main(){ char s[]="HI THERE!"; func1<char*, char, char, char>(s); return 0; }
注意事项
必须保证入参
s支持下标访问,且有效下标范围不小于sizeof...(Cs),否则会触发数组越界的未定义行为。
实现原理
可变参数模板的参数包展开只能在特定语法上下文完成,无法直接在函数体内按参数包长度循环生成s[0]、s[1]这类实参表达式。std::index_sequence是编译期工具,可以将参数包的长度(编译期常量sizeof...(Cs))转换为从0开始的连续编译期整数序列,再通过参数包展开一次性生成所有对应下标的实参,匹配func的参数要求。
内容的提问来源于stack exchange,提问作者joudia
相关产品推荐
相关产品推荐

