C++ -- variadic template (可变参数模板)

头歌MySQL数据库实训答案 有目录 头歌java实训答案集数据库部分一条一条的写,可鼠标手动粘贴,除特定命令外未分大小写。 第1关:创建数据库 第2关创建表 第3关:使用主键约束 第4关:外键约束 第5关:添加常用约束 MySQL数据库 - 数据库和表的基本操作(一) 第1关:查看表结构与修改表名 第2关:修改字段名与字段数据类型 第3关:添加与删除字段 第4关:修改字段的排列位置 第5关:删除表的外键约束 MySQL数据库 - 数据库和表的基本操作(二) 第1关:插入数据 第2关:更新数据 第3关:删除数据 MySQL数据库 - 单表查询( 阅读详情

C++11 语言核心的改进中,最为关注的有 rvalue reference (这里有一篇拙作),lambda,variadic template。rvalue 规则稍微复杂,但一旦理解和记住了,应用上就没有什么困难。lambda 其实是一个“很自然”的语言设施,除了语法稍显诡异之外,习惯了就能马上用上,而且是能广泛用上的好东西。variadic template 这个新特性不像前两者,它本身的语法规则并不复杂,但是应用的时候确比较费脑子,好在这个技术主要是用在库的实现中,一个实现得好的库,并不会让我们对实现的细节作任何的要求。

variadic template 特性本身是一个很自然的需求,它完善了 C++ 的模板设计手段。原来的模板参数可以使类和函数的参数类型“任意化”,如果再加上“参数个数的任意化”,那么在参数方面的设计手段就基本上齐备了,有了variadic template 显然可以让设计出来的函数或是类有更大的复用性。因为有很多处理都是与“处理对象的个数”关系不大的,比如说打屏(printf),比如说比较大小(max,min),比如函数绑定子(bind,function要对应各种可能的函数就要能“任意”参数个数和类型)。如果不能对应任意个参数,那么就总会有人无法重用已有的实现,而不得不再重复地写一个自己需要的处理,而共通库的实现者为了尽可能地让自己写的类(函数)能复用在更多的场景,也不得不重复地写很多的代码或是用诡异的技巧,宏之类的去实现有限个“任意参数”的对应。(像TR1中的 bind 等)。

一、基本语法

声明一个带有可变参数个数的模板的语法如下所示:

  1. template<typename ...Element> class tuple;
  2.  
  3. tuple<int, string> a;  // use it like this

在模板参数 Element 左边出现省略号 ... ,就是表示 Element 是一个模板参数包(template type parameter pack)。parameter pack(参数包)是新引入 C++ 中的概念,比如在这个例子中,Element 表示是一连串任意的参数打成的一个包。比如第2行中,Element 就是 int, string这个参数的合集。不仅“类型”的模板参数(也就是typename定义的参数)可以这样做,非类型的模板参数也可以这样做。比如下面这个例子:

  1. template<typename T, unsigned PrimaryDimesion, unsigned...Dimesions>
  2. class array { /**/ };
  3.  
  4. array<double, 3, 3> rotation_matrix; //3x3 ratiation matrix

现在我们知道parameter pack了,怎么在程序中真正具体地去处理打包进来的“任意个数”的参数呢?我原来以为,编译器会提供一些像get_param<1>(Element) 之类的内建的“参数抽取函数”给程序员使用结果不是!!看来我的思路还是太“过程式了”。其实 C++11 用的是 unpack 和类似函数重载似的“模板特化”来抽取参数的。这是应用 variadic tempate 最“坑爹”的部分,因为它要求对“递归”和“人肉代码展开”有一定的功力啊。还是看例子吧:

  1. template<typename... Elements> class tuple;
  2. template<typename Head, typename... Tail>
  3. class tuple<Head, Tail...> : private tuple<Tail...> {
  4.     Head head;
  5. public:
  6.     /* implementation */
  7. };
  8. template<>
  9. class tuple<> {
  10.     /* zero-tuple implementation */
  11. };

第1行声明了一个可以对应任意参数的tuple类,第2行到7行声明了这个类的一个部分特化,注意,这就是抽取参数的典型方法了。给个图还是最方便用来理解的:


(如果看不全,点击它可以看全图)

好吧,我觉得这个图是本篇博客中最有价值的部分了,转载一定要注明出处啊!

只说明一下针对 parameter pack 相对的另一个概念,模板参数后面带省略号 ... 就是一个解包(unpack),会把这个参数所表示的参数列表解开后去匹配新的模板,或是进行模板展开。其它的,我觉得有上面这个图,实在不需要再多费什么笔墨去讲这一部分了。

二、例子

新的标准库里,有很多个库都直接依赖于 variadic template 这个语言特性,比如,tuple,bind,function。但他们比较复杂,也不够“惊艳”。C++ 老爸的 C++11 的 FQA 和 Wikipedia 的例子都是“类型安全”的printf:

void printf(const char *s)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                throw std::runtime_error("invalid format string: missing arguments");
            }
        }
        std::cout << *s++;
    }
}
 
template<typename T, typename... Args>
void printf(const char *s, T value, Args... args)
{
    while (*s) {
        if (*s == '%') {
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                std::cout << value;
                // call even when *s == 0 to detect extra arguments
                printf(s + 1, args...);
                return;
            }
        }
        std::cout << *s++;
    }
    throw std::logic_error("extra arguments provided to printf");
}

这个例子确实很棒,够短。仅仅X行的代码中,就用到了选择(if)和循环(while),递归(printf自身的递归),重载(cout的<<对种输出类型的重载),异常。这个例子不细讲,大家试着用“上面的图”来试试分析一下吧。(这个例子用来面试,让面试者来解析下是不是不错?……)

三、杂想

这里有篇文章有一些关于这个特性加入 C++ 的动机,简而言之,像 function ,bind 之类如果没有这个特性,实现起来会非常的麻烦,而且这样实现出来的代码也会使得编译时间变得很长。

image

你看,如果要支持39个参数,编译时间会到700秒。而使用 variadic template 之后,代码小了 40 K,同时各种参数个数的情况下编译时间都小于 1 秒。

这很好。但是,这个特性用起来真的不是那么容易,你也看到了。在和其它的特性一起使用的时候(多重继承,右值引用)等在一起的时候,会更加地“复杂”。但它是一个利器,用得好,会造出非常好用的库。否则,我们就用库好了,不要为去学习,记住和非要在日常编程中使用它而烦恼了。

四、参考资料

  1. Variadic Templates for GCC:http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html
  2. 维基百科:http://en.wikipedia.org/wiki/Variadic_template
  3. C++11当时的提案:N2080 (这个特别好,或是最好,我所见过的)


永磁同步电机定子槽型设计实战:从梨形槽到矩形槽的NVH优化之路 本文深入探讨了永磁同步电机定子槽型设计在NVH优化中的关键作用,对比了梨形槽与矩形槽的性能差异。通过Ansys Maxwell仿真和实际案例,揭示了矩形槽在提升槽满率、降低电磁噪声方面的优势,并总结了五大设计黄金法则,为电机设计工程师提供了实用指导。 阅读详情

相关推荐

手把手教你排查libstdc++.so.6版本问题:从GLIBCXX缺失到完美解决

本文深入解析Linux系统中常见的GLIBCXX版本缺失问题,以`ImportError: /lib/x86_64-linux-gnu/libstdc++.so.6: version 'GLIBCXX_3.4.29' not found`为例,从动态链接原理入手,提供使用`strings`和`find`命令的诊断方法,并详细对比了四种解决方案的优缺点。文章重点推荐通过设置`LD_LIBRARY_PATH`或更新系统库的安全策略,并最终建议使用Docker容器化技术实现环境依赖的根治与统一管理。

j7k8l的博客 300

C++11新特性(侯捷)——课程笔记(二)

本部分包括的内容为Variadic Templates(可变模板参数),这部分似乎是个概述,我看到后面有好几节课也是这个主题。

NiuYutao的博客 878

PT静态时序分析实战:从基础命令到高级报告解析

本文详细介绍了PT(PrimeTime)静态时序分析(STA)的实战技巧,从基础命令如pt_shell和report_timing的使用,到高级报告解析与问题排查。通过丰富的实例和脚本示例,帮助工程师快速掌握时序分析的核心技能,提升芯片设计验证效率。

weixin_29289821的博客 953

C++11&14新标准——Variadic templates(数量不定的模板参数)

C++11&14新标准——Variadic templates(数量不定的模板参数)

weixin_48956191的博客 1104

Innovus快捷键大全:从入门到精通的效率提升指南

本文是Innovus快捷键从入门到精通的效率提升指南,旨在帮助芯片后端设计工程师通过掌握核心快捷键,将重复性鼠标操作转化为高效的肌肉记忆,从而显著提升版图设计、编辑和分析的工作流速度。文章系统讲解了视图导航、对象选择编辑、流程管理等关键快捷键组合,并提供了个性化配置与实战策略,助力工程师突破效率瓶颈,实现人机合一的流畅设计体验。

silver的专栏 796

ESP32驱动GC9A01圆形屏实战:Arduino平台LVGL移植与图像显示优化

本文详细介绍了在Arduino平台上使用ESP32驱动GC9A01圆形屏的实战指南,包括硬件连接、LVGL移植与图像显示优化。通过SPI配置、LVGL库安装和双缓冲机制等技巧,帮助开发者快速实现高效显示效果,适用于智能家居控制面板等应用场景。

weixin_29182481的博客 733

Variadic Templates [参数不定的模板参数] 特性与优缺点

Variadic Template是C++11的一个很重要的特性: 参数个数:利用参数个数逐一递减的特性,实现递归调用; 参数类型:参数个数逐一递减导致参数类型也逐一递减; Variadic Template 的缺点: 只能在同一个代码文件中调用,如果在静态库或者动态库则无法正常调用 Variadic Template是一种与编译有关的特性,属于静态的;编译器编译时会扫描本文件中所有的调用...

Silent_DXX的专栏 442

基于R语言的现代贝叶斯统计学方法(贝叶斯参数估计、贝叶斯回归、贝叶斯计算)实践

贝叶斯统计学是一门基本思想与传统基于频率思想的统计学完全不同的统计学方法;它以其灵活性和先进性在现代的统计学中占据着重要的地位。贝叶斯统计学是开展科学研究不可缺少的重要手段,但是,因为其思想、技术和方法都与传统统计学有着较大区别;且其计算中涉及马尔科夫、蒙特卡罗和吉布斯采样等现代计算方法,对使用者经验和能力构成了很大的挑战。

AAIshangyanxiu的博客 679

跟我学c++中级篇——c++11中的模板变参化

对C++11及以后的模板变参化进行分析和举例说明

fpcc的专栏 1666

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

ProceduralMan的博客 7410

matlab 一维相位解缠

一维相位解缠算法的matlab代码实现。

点云侠的博客 372

C++可变参数模板(variadic template)详细介绍及代码举例

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34061042的博客 328

【AI智能体】Codex 生成高质量电商套图实战操作详解

Codex 生成高质量电商套图实战操作详解

congge 4510

c++11新特性(3)之可变参数模板(variadic template)

可变参数模板(variadic template) 听说这是一个c++新特性 中最大的改动,我的认识有限只能写一些十分基础的理解,但我会持续更新。 所谓可变参数模板,就是模板函数的参数是可以变化的,不是一个、两个参数,而是一包参数,这一包参数可以是0个到n个,这种将参数打包的操作就是可变参数模板。具体的语法如下: template<typename T,typename... Arg...

请叫我少爷的博客 2433

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C++11中可变参数个数的模板(variadic template)

C++11正式标准是2011年就出来了,前一段时间就听说它增加了不少功能,但一直没用到它。直到最近需要用到可变参数个数的模板,用之前的语法很累赘也存在缺陷,这时查看C++11发现有我需要的类似功能。下面是我做的一点尝试。   VS2012支持C++11中的部分标准,其中包括可变参数个数的模板(variadic template),但必须安装微软在2012年11月出版的vc_compilerCT

herojia的专栏 3391

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++ Variadic Template (可变参数模板)

可变参数模板是C++模板元编程的基石,提供了:✅类型安全的可变参数函数✅零开销的编译时抽象✅完美转发支持✅灵活的接口设计掌握可变参数模板,是成为C++高级开发者的必经之路!

2501_93283929的博客 330

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

C++11标准新增可变参数模板(variadic template)

  C++ 11标准新增加了“可变参数模板”(variadic template)。   可变参数模板中,模板的typename个数是可变长度的。下面给个例子,已在g++ 4.6.1上编译通过,并成功运行。 /* * C++11标准  可变参数模板(variadic template)  样例 * * * Copyright © ...

weixin_30710457的博客 117

C++11 可变参数模板 (Variadic Template)

C++17 才有原生折叠表达式,C++11 可用。

fangfanglovezhou的博客 47

C++11新特性(68)- 可变参数模板(variadic template)

可变参数函数 C语言中,可变参数函数可以说是一个比较神奇的存在。例如最常用的printf函数,它的原型如下: 它的第一个参数是const char*类型的format,后面参数的类型和名称都没有定义,只有三个点。   虽然从C语言编译的角度来讲,在这个位置程序员可以写任意个数,任意类型的参数,实际上printf函数根据format指定的格式字符串来使用后面指定的 实参值,个数少了或者类...

面向对象思考 4028

[C++] Variadic Fuction Template 可变参数函数模板

可变参数函数模板(variadic function template)主要使用了包扩展(pack expansion)的方式,即”...”,把一个模式(pattern)扩展为包中每一个元素(element)的形式;可变参数函数模板一般会使用递归(recursive)来处理包(pack)参数。一般来说需要两个函数: 需要一个非可变参数(nonvariadic)函数模板,当结束递归,最后一次调用时...

SMUElpmis's Blog 574

没有与参数列表匹配的构造函数_C++ 可变参数模板variadic template

可变参数模板可变参数模板(variadic template)为一个接受可变数目参数的模板函数或模板类。参数包(parameter packet)可变数目的参数。模板参数包(template parameter packet)表示零个或多个模板参数。函数参数包(function parameter packet)表示零个或多个函数参数。用省略号指出一个模板参数或函数参数表示一个包。用class.....

weixin_40002336的博客 804

c语言template的参数是什么,C++11新特性(68)- 可变参数模板(variadic template)

可变参数函数C语言中,可变参数函数可以说是一个比较神奇的存在。例如最常用的printf函数,它的原型如下: 它的第一个参数是const char*类型的format,后面参数的类型和名称都没有定义,只有三个点。虽然从C语言编译的角度来讲,在这个位置程序员可以写任意个数,任意类型的参数,实际上printf函数根据format指定的格式字符串来使用后面指定的实参值,个数少了或者类型错误常常会导致错误。...

weixin_34284072的博客 254

C++11-14 第1讲 Variadic Template(可变参数函数模板)

...从C就存在了 版权说明:本博文属于个人笔记,本人保留对本文的所有权益,未经许可不得以任何形式转载。 代码略去,可参考:https://blog.youkuaiyun.com/Cherish_2014/article/details/49256801 1.递归分解可变参数函数的参数包 #include&lt;iostream&gt; #include&lt;bitset&gt; using na...

蒟蒻菜鸡的博客 962
上一篇: C++实现委托机制之完整代码实现(一)
下一篇: C++实现委托机制(二)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值