You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 11:16:12