C++17中如何转换转发参数包并两两合并相邻参数(优先无递归)
在C++17中实现参数包两两合并转发
原代码无法编译的核心问题是:尝试直接将剩余参数包整体传递给仅接受两个模板参数的CombinedType,且未实现参数包的两两分组逻辑。下面提供两种可行方案,优先满足非递归需求,同时给出更直观的递归实现。
非递归实现(C++17)
利用C++17的std::index_sequence、折叠表达式和std::get,可以实现无递归的参数包两两分组:
#include <iostream> #include <string> #include <utility> #include <tuple> template <typename T1, typename T2> struct CombinedType { T1 v1; T2 v2; }; template<typename T1, typename T2> void print_combined(CombinedType<T1, T2> v) { std::cout << v.v1 << ", " << v.v2 << "\n"; } // 批量处理CombinedType实例 template<typename... Combineds> void do_combined(Combineds... cs) { (print_combined(cs), ...); // C++17折叠表达式展开调用 } // 辅助模板:通过索引提取参数并两两组合 template <typename... Args, std::size_t... Idx> void do_single_impl(Args&&... args, std::index_sequence<Idx...>) { auto args_tuple = std::forward_as_tuple(std::forward<Args>(args)...); do_combined( CombinedType{ std::get<2 * Idx>(args_tuple), std::get<2 * Idx + 1>(args_tuple) }... ); } // 对外接口:要求参数数量为偶数 template<typename... Args> void do_single(Args&&... args) { static_assert(sizeof...(Args) % 2 == 0, "参数数量必须是偶数"); do_single_impl( std::forward<Args>(args)..., std::make_index_sequence<sizeof...(Args) / 2>{} ); }
优雅递归实现
如果觉得非递归的索引逻辑不够直观,递归方案代码更简洁易懂:
#include <iostream> #include <string> #include <utility> template <typename T1, typename T2> struct CombinedType { T1 v1; T2 v2; }; template<typename T1, typename T2> void print_combined(CombinedType<T1, T2> v) { std::cout << v.v1 << ", " << v.v2 << "\n"; } template<typename... Combineds> void do_combined(Combineds... cs) { (print_combined(cs), ...); } // 递归终止条件:无剩余参数 void do_single() {} // 递归处理:每次取前两个参数组合,转发剩余参数 template<typename T1, typename T2, typename... Rest> void do_single(T1&& v1, T2&& v2, Rest&&... rest) { do_combined(CombinedType<T1, T2>{ std::forward<T1>(v1), std::forward<T2>(v2) }); do_single(std::forward<Rest>(rest)...); }
测试与运行
两种方案都可以直接用你的测试代码验证:
int main() { do_single('1', 2, "3", 4u, std::string("5"), '6'); }
输出结果:
1, 2 3, 4 5, 6
关键细节
- 两种方案都支持完美转发,保留参数的左值/右值属性,避免不必要的拷贝。
- 非递归方案通过
std::index_sequence生成索引,将参数包按偶数/奇数位置两两配对,一次性展开所有组合。 - 递归方案逻辑直观,每次处理一对参数,直到参数包为空,代码量更少,易读性更高。
内容的提问来源于stack exchange,提问作者Richard W
相关产品推荐
相关产品推荐

