玩转OurBMC第二十八期:现代C++模板元编程
【栏目介绍:“玩转OurBMC” 是OurBMC社区开创的知识分享类栏目,主要聚焦于社区和BMC全栈技术相关基础知识的分享,全方位涵盖了从理论原理到实践操作的知识传递。OurBMC社区将通过 “玩转OurBMC” 栏目,帮助开发者们深入了解到社区文化、理念及特色,增进开发者对BMC全栈技术的理解。 欢迎各位关注 “玩转OurBMC” 栏目,共同探索OurBMC社区的精彩世界。同时,我们诚挚地邀请各位开发者向 “玩转OurBMC” 栏目投稿,共同学习进步,将栏目打造成为汇聚智慧、激发创意的知识园地。】 OpenBMC的基础软件包(如sdbusplus、bmcweb等)为适配内存、算力受限的嵌入式系统并保障流畅运行,采用了 C++ 模板元编程(TMP,Template Metaprogramming)技术。该技术通过在编译期完成数据类型属性的获取与校验,消除了类型转换带来的性能损耗,实现了程序运行时类型转换的零开销。此外,现代 C++ 模板元编程可将原本运行时的计算开销转移至编译阶段,运行时直接复用编译期常量计算(Compile-time Constant Calculation)的结果;同时它能剔除无效代码分支,生成更精简的二进制机器码,进一步提升程序运行效率。值得注意的是,模板元编程作为泛型编程的核心组成部分,通过解耦数据与算法逻辑,有效提高了代码复用性、降低了代码冗余度,使整体代码更简洁高效。本文对现代 C++ 模板元编程技术进行初步梳理与介绍,旨在帮助读者理解 OpenBMC 中采用该技术的代码模块设计思路与实现逻辑。 本章节引入函数重载和函数模板,分析C++模板元编程在编译期间对数据类型做推导,对模板实例化。 函数重载(Function Overloading)是在同一作用域内,定义多个同名但参数列表不同(参数类型、数量、顺序不同)的函数,编译器会根据调用时的实参类型、数量,自动匹配对应的函数版本。 函数模板(Function Template)是一个通用函数模板,用类型参数(如typename T)替代具体类型,编译器会根据调用时的实参类型,自动实例化出对应类型的函数,实现一套逻辑适配所有类型。 上面的表格,对函数重载和函数模板,做了对比分析。接下来,以下面的框图,对函数模板的推导、替换、决议,做个简要的说明。 模板元编程与函数模板均在编译阶段完成类型推导,二者均充当C++的“编译期代码生成器”,有效简化代码结构;其中模板元编程更进一步,能够借助编译期的计算能力,完成逻辑运算、类型推导、数值计算等操作,并直接生成最终可执行的代码。 模板元编程之所以能实现编译期条件判断与类型筛选,其核心底层机制源于 SFINAE 规则——即 “Substitution Failure Is Not An Error”(中文译为“替换失败不是错误”)。该规则的核心要义为:当编译器尝试将模板参数替换为具体类型时,若某一替换过程出现“语法合法但逻辑不成立”的失败(例如访问不存在的类型成员、调用参数不匹配的函数等场景),编译器不会直接抛出编译错误,而是舍弃该模板版本,继续尝试重载集合中的其他候选版本。 下图是从 OpenBMC 的软件包 sdbusplus 源码头文件 “type_traits.hpp”,摘取的代码片段,通过该图的代码,简单的介绍 SFINAE 规则。 从上图可以看到,序列式Vector容器和自定义的Bar,因为没有提供名称为find的成员函数。编译器在匹配类 has_member_find 的成员函数check替换失败后,并没有出现编译报错,而是静默跳过该模板版本,继续尝试匹配其他重载版本。 使用免费开源的 C++ 代码可视化工具cppinsights工具对介绍SFINAE规则的示例程序,转换为编译器视角的展开的 C++ 代码,理解SFINAE这一规则。在下图中,编译器分别实例化了Foo和Bar两个类,生成了class has_member_find<Foo&>和class has_member_find<Bar>,并在编译期间,如图中红色箭头所示,对类Foo和类Bar,是否提供find成员函数,做了判决。即check检测到类Foo包含了名称为find的成员函数,给成员变量value赋值为true的类型,而类Bar的value成员变量为false。 最后,介绍下模板元编程在编译期的常量计算,以下图的代码示例,该代码的功能是计算一个整数的平方值。 测试整数9的平方值,在代码第8行,判断计算结果。从下图中可以看到,在编译阶段,编译器计算了9的平方值,并因为调用static_assert判断时,检测到计算结果,与测试预设的结果不相等,在编译阶段报错。 本文简要介绍了 C++ 模板元编程的核心概念、底层实现机制及核心功能,旨在帮助读者理解OpenBMC项目中采用 C++ 模板元编程技巧编写的代码片段。自 C++11 将模板元编程相关能力纳入标准库起,这一技术正逐步完成从“编程黑魔法”到工程化实践的转变,感兴趣的读者可基于本文进一步深入学习与探索。 欢迎大家关注OurBMC社区,了解更多BMC技术干货。01 函数重载与函数模板

表- 1 函数重载和函数模板
02 SFINAE浅析



03 编译期计算


OurBMC社区官方网站:
https://www.ourbmc.cn/