C++ 17 std::apply

C++ 17 std::apply
枫C++ 17 std::apply
std::apply的作用可以概括成一句话:把 tuple 里的元素拆开,作为函数参数传进去。
它是tuple、可调用对象和模板工具之间的一座桥。
1. 为什么需要 std::apply?
假设你有一个函数:
1 | int add(int a, int b, int c) |
同时你手里拿到的是:
1 | std::tuple<int, int, int> t{1, 2, 3}; |
以前如果要调用这个函数,通常得手动写:
1 | add(std::get<0>(t), std::get<1>(t), std::get<2>(t)); |
而 std::apply 可以直接完成这件事。
2. 基本示例
1 |
|
输出:
1 | 6 |
3. 不只适用于普通函数
std::apply 也可以配合 lambda 使用:
1 | auto t = std::make_tuple(10, 20); |
还可以配合函数对象:
1 | struct Print |
4. 一个常见场景
有时我们会把参数先打包成 tuple,后面再统一执行某个调用:
1 |
|
这种模式在任务调度、延迟调用、泛型封装里很常见。
5. 配合结构化绑定理解
你可以把它理解成另一种“解包 tuple”的方式:
- 结构化绑定:把 tuple 拆到多个变量里
std::apply:把 tuple 拆成函数参数
两者思想上是相通的。
6. 使用时要注意的点
6.1 tuple 元素顺序必须和函数参数顺序对应
如果顺序不对,调用就会失败,或者逻辑错误。
6.2 tuple 中元素类型也必须匹配
它不会帮你自动做复杂的参数重排。
6.3 适合泛型封装场景
如果只是写死的三四个参数,手写调用也不是不行;std::apply 的价值更多体现在通用代码里。
总结
std::apply 是一个很好理解、也很实用的小工具。
它把 tuple 拆成可调用对象的参数列表,在延迟调用、泛型封装和参数转发场景里很顺手。只要你项目里开始频繁接触 tuple,这个接口基本都会遇到。














