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

如何使用折叠表达式展开parameter pack并传递每个元素的对应索引

实现方案

该需求完全可以通过C++17引入的折叠表达式实现,核心思路是结合编译期索引序列std::index_sequence和逗号折叠表达式完成参数包展开,以下是可运行的实现:

C++20 最简写法(支持模板lambda)

#include <utility> // 用于std::index_sequence、std::forward等工具

// 你提供的目标函数
struct Record {}; // 补全Record类型方便编译
template<typename T>
void addToRecord(Record& rec, int idx, T&& val)
{
    // Do some stuff.
}

template<typename... ARGS>
void addRecord(ARGS&& ...values)
{
    Record rec;
    // 生成索引序列+折叠表达式展开调用
    [&]<std::size_t... Is>(std::index_sequence<Is...>, auto&& vals) {
        // 逗号折叠表达式,按顺序执行每个addToRecord调用
        (addToRecord(rec, static_cast<int>(Is), std::get<Is>(vals)), ...);
    }(
        std::make_index_sequence<sizeof...(ARGS)>{}, 
        std::forward_as_tuple(std::forward<ARGS>(values)...)
    );

    // 后续处理rec的逻辑
}

C++17 兼容写法(无模板lambda)

如果需要兼容C++17标准,可以将lambda的逻辑抽为独立的辅助模板函数:

#include <utility>

struct Record {};
template<typename T>
void addToRecord(Record& rec, int idx, T&& val)
{
    // Do some stuff.
}

// 辅助展开函数
template<typename Tuple, std::size_t... Is>
void batchAddToRecord(Record& rec, Tuple&& vals, std::index_sequence<Is...>)
{
    (addToRecord(rec, static_cast<int>(Is), std::get<Is>(std::forward<Tuple>(vals))), ...);
}

template<typename... ARGS>
void addRecord(ARGS&& ...values)
{
    Record rec;
    batchAddToRecord(
        rec,
        std::forward_as_tuple(std::forward<ARGS>(values)...),
        std::make_index_sequence<sizeof...(ARGS)>{}
    );

    // 后续处理rec的逻辑
}

原理解释

  • 首先通过std::make_index_sequence<sizeof...(ARGS)>生成和参数包长度完全一致的编译期整数序列0,1,2,...,N-1,每个整数对应该位置参数的索引
  • 用std::forward_as_tuple将参数包打包为元组,保留所有参数的左右值属性,方便按索引取值
  • 这里使用的是一元右逗号折叠,展开后会按顺序执行每个索引对应的addToRecord调用,执行顺序和参数包的传入顺序完全一致,和递归实现的效果完全相同。

如果你的参数包长度可能超过int的最大值,建议将addToRecord的idx参数类型改为std::size_t,避免类型转换的溢出风险。

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:51:01