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

如何从可变参数模板生成std::function类型的std::tuple

解决方案

首先,你要的函数模板声明可以直接靠模板参数推导实现,不用复杂操作:

template <typename... Ts>
void f(std::tuple<Ts...>& data, std::tuple<std::function<void(Ts&)>...> functions);

当你传入std::tuple<int, std::string>&这类参数作为第一个参数时,第二个参数会自动被推导为对应类型的std::function元组——比如上面的例子就会推导成std::tuple<std::function<void(int&)>, std::function<void(std::string&)>>,完全符合你的需求。

如果需要在函数内部遍历两个元组,用对应位置的函数处理data里的元素,这时候才需要用到std::index_sequence来展开参数包,具体实现分两步:

1. 写辅助展开函数

我们需要一个带索引序列的辅助函数,用来逐个访问元组元素:

template <typename... Ts, std::size_t... Idx>
void f_impl(std::tuple<Ts...>& data, const std::tuple<std::function<void(Ts&)>...>& functions, std::index_sequence<Idx...>) {
    // 用C++17折叠表达式逐个调用函数,传入对应元素的引用
    (std::get<Idx>(functions)(std::get<Idx>(data)), ...);
}

这里的折叠表达式(...,)会把每个索引对应的函数调用依次展开执行,简洁高效。

2. 对外的主函数

主函数负责生成匹配的索引序列,然后把调用转发给辅助函数:

template <typename... Ts>
void f(std::tuple<Ts...>& data, std::tuple<std::function<void(Ts&)>...> functions) {
    // 自动生成0到元素数量-1的索引序列
    f_impl(data, functions, std::index_sequence_for<Ts...>());
}

std::index_sequence_for<Ts...>会根据模板参数包的大小,生成刚好匹配元组元素数量的索引序列,不用手动写索引。

实际使用示例

#include <tuple>
#include <functional>
#include <iostream>

// 把上面的函数实现放在这里

int main() {
    std::tuple<int, std::string> data{42, "hello"};
    auto functions = std::make_tuple(
        [](int& num) { num *= 2; },
        [](std::string& str) { str += " world"; }
    );

    f(data, functions);

    // 输出:82 hello world
    std::cout << std::get<0>(data) << " " << std::get<1>(data) << std::endl;
    return 0;
}

额外说明

  • 如果你的编译器不支持C++17,可以用递归展开的方式替代折叠表达式,但折叠表达式写法更简洁。
  • std::index_sequence是C14的特性,要是需要兼容C11,自己写个简单的索引序列模板也不难。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 09:33:39