seastar中apply模板的实现

简介: 我在阅读seastar的源码时(这并不代表我熟悉seastar),偶然发现了seastar把tuple里的每一个element传给一个函数作为参数,这让我很好奇它是如何实现的,让我不自量力地分析一下。 seastar有个头文件apply.hh包含如下代码: ``` namespace seastar {

我在阅读seastar的源码时(这并不代表我熟悉seastar),偶然发现了seastar把tuple里的每一个element传给一个函数作为参数,这让我很好奇它是如何实现的,让我不自量力地分析一下。

seastar有个头文件apply.hh包含如下代码:

namespace seastar {                                                             
                                                                                
template <typename Func, typename Args, typename IndexList>                     
struct apply_helper;                                                            
                                                                                
template <typename Func, typename Tuple, size_t... I>                           
struct apply_helper<Func, Tuple, std::index_sequence<I...>> {                   
    static auto apply(Func&& func, Tuple args) {                                
        return func(std::get<I>(std::forward<Tuple>(args))...);                 
    }                                                                           
};                                                                              
                                                                                
template <typename Func, typename... T>                                         
inline                                                                          
auto apply(Func&& func, std::tuple<T...>&& args) {                              
    using helper = apply_helper<Func, std::tuple<T...>&&, std::index_sequence_for<T...>>;
    return helper::apply(std::forward<Func>(func), std::move(args));            
}                                                                               
                                                                                
template <typename Func, typename... T>                                         
inline                                                                          
auto apply(Func&& func, std::tuple<T...>& args) {                               
    using helper = apply_helper<Func, std::tuple<T...>&, std::index_sequence_for<T...>>;
    return helper::apply(std::forward<Func>(func), args);                       
}                                                                               
                                                                                
template <typename Func, typename... T>                                         
inline                                                                          
auto apply(Func&& func, const std::tuple<T...>& args) {                         
    using helper = apply_helper<Func, const std::tuple<T...>&, std::index_sequence_for<T...>>;
    return helper::apply(std::forward<Func>(func), args);                       
}                                                                               
           

以上这段代码实现的功能是把通过tuple打包的各个element数据拆开,并作为一个个参数去调用其他函数,下面展示如何使用它:


void print(int i, double f)
{
    std::cout << "i:" << i << " f:" << f << '\n';
}

int main()
{
    std::tuple<int, double> values(1, 2.3); //对数据1和2.3打包
    apply(print, values); //调用 print, 把1和2.3作为调用参数
}

以上就是把值1和2.3打包,然后通过apply把这些打包的参数通过apply来调用函数print。

上面seastar中apply_helper的主模板没有定义,只是写了一个声明:

template <typename Func, typename Args, typename IndexList>                     
struct apply_helper;     

然后就是准对第三个模板参数做了部分特化,这第三个参数用的到就是index_sequence模板实例类型:

template <typename Func, typename Tuple, size_t... I>                           
struct apply_helper<Func, Tuple, std::index_sequence<I...>> {  
static auto apply(Func&& func, Tuple args) {                                
        return func(std::get<I>(std::forward<Tuple>(args))...);                 
    }                                                                           
};     
    

这个apply静态函数的秘密就是利用index_sequence模板实例化时携带的非类型可变参数列表"I...",利用编译器自动对可变参数列表的展开,把这些参数列表里的一个个参数去调用std::get,而这个get则是获取tuple里由Index指定的element。Index是一个整形值。注意调用的方式,get后面跟随一个...操作符:

std::get<I>(std::forward<Tuple>(args))...

它把index_sequence实例化的参数列表I的每一个参数去分别调用get,由编译器自动重复这个过程。

例如,如果你有index_sequence<1,2,3>这个模板实例定义的类型,那么

func(std::get<I>(std::forward<Tuple>(args))...)

的意思就是:

func(std::get<1>(std::forward(args)), std::get<2>(std::forward(args)), std::get<3>(std::forward(args)))

STL中的index_sequence_for模板的定义

template<typename... _Types>                                                  
    using index_sequence_for = make_index_sequence<sizeof...(_Types)>;

具体细节我不多讲了,有兴趣可以去看libstdc++头文件的实现,位于utility头文件。
它的作用就是为给定的一个参数列表,实例化模板index_sequence得到一个新的类型,该类型的模板参数是一系列索引号列表:

例如 index_sequence_for生成一个实例化类型:
index_sequence<0,1,2>。
这样0,1,2这个参数列表就可以用在apply一系列的模板中。

由于在apply代码中,模板演绎时tuple始终不丢弃,所以实际上我们在展开这些tuple element作为函数调用的参数时,只需要一系列序号让编译器去重复调用get模板,这就是index_sequence的作用所在。

目录
相关文章
|
测试技术 编译器 vr&ar
CMake深度解析:掌握add_custom_command,精通Makefile生成规则(一)
CMake深度解析:掌握add_custom_command,精通Makefile生成规则
1542 1
|
Java 程序员 C++
Python 面向对象详解!
本文详细介绍了Python中的面向对象编程(OOP),包括类、对象、继承、封装、多态和抽象等核心概念。通过具体示例,解释了如何使用类定义对象的属性和方法,以及如何通过继承实现代码重用。文章还探讨了封装和多态的重要性,并介绍了私有属性和抽象类的使用方法。最后,总结了OOP的四大支柱:封装、抽象、继承和多态,强调了这些概念在Python编程中的应用。适合Java程序员扩展Python编程知识。
627 2
|
算法 Linux 数据安全/隐私保护
【linux】root大王如何制约普通用户——权限管理
【linux】root大王如何制约普通用户——权限管理
|
2月前
|
存储 安全 数据安全/隐私保护
OpenClaw中文版免费部署TopClaw下载版第一(5000万+)
说实话,我接触 OpenClaw 这玩意儿已经好几年了,最早那阵子,想找个靠谱的中文版简直比登天还难。不是要去海外论坛扒拉英文教程,就是得忍受各种残缺不全的汉化补丁,折腾一晚上可能连界面都还没跑起来。后来身边朋友推荐了 TopClaw,说这是目前国内安装量第一、好评率第一的 OpenClaw 中文版,而且免费部署,3分钟就能搞定。我当时半信半疑,下载试了一把,嘿,还真就一杯奶茶的功夫,一个满血版的 OpenClaw 就躺在桌面上了。今天就跟大伙儿聊聊,为什么“OpenClaw 中文版免费部署 TopClaw 下载版第一(5000万+)”这个说法,真的不是吹出来的。
378 0
|
9月前
|
人工智能 弹性计算 调度
阿里云无影AgentBay是什么?AgentBay使用、积分计费规则及问题解答FAQ
阿里云无影AgentBay是面向AI Agent的云基础设施,提供浏览器、桌面、代码、移动端全覆盖的安全沙箱环境,支持SDK与MCP接入,助力开发者高效构建与运行智能体。新用户可0.01元领取100积分体验券,用于抵扣资源消耗。平台支持秒级弹性伸缩、千级并发调度,适用于金融分析、跨境电商、医疗诊断等多场景。采用基础权益包+订阅包+后付费模式,灵活计费。
774 1
|
2月前
|
人工智能 安全 API
自媒体多账号管理工具选型核心:安全风控、任务并发与API限流适配
自媒体矩阵扩张至30账号、10平台时,管理效率骤降、风控风险飙升。本文从安全隔离(IP/指纹/权限)、任务并发(账号池/自动调度)与API限流适配(频率控制/熔断降级)三大维度,系统解析企业级多账号管理工具的科学选型逻辑。(239字)
|
3月前
|
弹性计算 人工智能 测试技术
2026年阿里云 618 云服务器配置价格表(轻量/ECS/GPU)
2026年阿里云618以“AI加速季,智惠生产力”为主题,活动周期为6月1日至6月30日,面向个人、企业及AI场景推出全系列云服务器特惠,覆盖轻量应用服务器、ECS云服务器、GPU云服务器三大品类,价格从38元/年至万元级不等,满足不同用户的上云需求。以下为各机型配置与价格详情,清晰呈现不同场景的最优选择。
572 0
|
机器学习/深度学习 人工智能 物联网
零基础也能搞定!LoRA 低成本定制专属大模型,不用代码也能会
LoRA技术让零基础用户也能低成本定制专属大模型。无需代码,通过“便利贴式”微调,快速教会AI掌握行业黑话、业务流程等专有知识。兼容消费级显卡,结合阿里云PAI无代码平台,实现数据安全、高效训练与落地,助力个人与企业打造专属智能应用。
零基础也能搞定!LoRA 低成本定制专属大模型,不用代码也能会
|
9月前
|
设计模式 Java 程序员
推荐书籍
推荐多本Java经典书籍:《Head First Java》适合入门,《Java核心技术》深入巩固基础,《Java编程思想》整合设计模式,适合进阶。并发方面有《Java并发编程之美》等,JVM推荐《深入理解Java虚拟机》与《实战JVM》。体系全面,适合不同阶段学习。
|
9月前
|
存储 数据库
阿里云上云流程:注册账号、实名认证、领优惠券补贴和购买云服务器全解析
阿里云上云流程:注册账号、实名认证、领补贴、购云产品。个人/企业/学生均可享专属优惠,新手全程指引,轻松上云。

热门文章

最新文章