c++11新特性:变长参数模板详解

2023-05-16

这里写目录标题

    • C++11 变长参数模板
    • 变长函数参数包
    • 如何解参数包
      • sizeof()获得函数参数个数
      • 递归模板函数
      • 变参模板展开
    • 结论

C++11 变长参数模板

在C++11之前,无论是类模板 还是函数模板,都只能按其指定的样子,接受一组固定数量的模板参数;

这已经大大提升了代码的复用!

在C++11之后,加入了新的表示方 法,允许任意个数、任意类别的模板参数,同时也不需要在定义时将参数的个数固定。更加像”黑魔法“了。

template<typename... Ts> class Magic;

模板类 Magic 的对象,能够接受不受限制个数的 typename 作为模板的形式参数,例如下面的定义:

class Magic<int,
std::vector<int>,
std::map<std::string,
std::vector<int>>> darkMagic;

既然是任意形式,所以个数为 0 的模板参数也是可以的:class Magic<> nothing;。 如果不希望产生的模板参数个数为 0,可以手动的定义至少一个模板参数:

template<typename Require, typename... Args> class Magic;

变长函数参数包

除了在模板参数中能使用表示不定长模板参数外,函数参数也使用同样的表示法代表不定长参数。

传统 C 中的 printf 函数,虽然也能达成不定个数 的形参的调用,但其并非类别安全。而 C++11 除了能定义类别安全的变长参数函数外,还可以使类似 printf 的函数能自然地处理非自带类别的对象。除了在模板参数中能使用 … 表示不定长模板参数外, 函数参数也使用同样的表示法代表不定长参数,这也就为我们简单编写变长参数函数提供了便捷的手段, 例如:

template<typename... Args> 
void printf(const std::string &str, Args... args);

其中,Argsargs 分别代表模板与函数的变长参数集合, 称之为参数包 (parameter pack)。参数包必须要和运算符"…"搭配使用。

如何解参数包

长参数模板中,变长参数包无法如同一般参数在类或函数中使用;这个很好理解!

因为在栈中,我们需要先知道函数有多少个参数,才可以入栈,但是我们不知道变长参数有多长,所以需要特殊手法!

sizeof()获得函数参数个数

首先,我们可以使用 sizeof… 来计算参数的个数,:

template<typename... Ts>
void magic(Ts... args) 
{
	std::cout << sizeof...(args) << std::endl;
}

递归模板函数

递归去获得所有参数,是非常容易想到的方法,这种方法不断递归地向函数传递模板参数,进而达到递归遍历所有模板参数的目的。

printf 会不断地递归调用自身:函数参数包 args... 在调用时, 会被模板类别匹配分离为 T valueArgs... args。 直到 args... 变为空参数,则会与简单的 printf(const char *s) 形成匹配,退出递归。

//递归模板函数
template<typename T0>
void printf1(T0 value)
{
	std::cout << value << std::endl;
}
template<typename T, typename... Ts>
void printf1(T value, Ts... args) 
{
	std::cout << value << std::endl;
	printf1(args...);
}
int RecursiveTemplateFunc() 
{
	printf1(1, 2, "123", 1.1);
	return 0;
}

变参模板展开

上面的递归很容易理解,但是比较繁琐,那么还有没有什么好方法呢?

在 C++17 中增加了变参模板展开的支持,于是你可以在一个函数中完 成 printf 的编写:

//变参模板展开
template<typename T0, typename... T>
void printf2(T0 t0, T... t) 
{
	std::cout << t0 << std::endl;
	if constexpr (sizeof...(t) > 0) 
		printf2(t...);
}

结论

模板作为C++中的”黑魔法“般的武器,学起来比较难,但当掌握后,确实非常高级,变长参数模板对我们写模板有很大的帮助!

本文的代码地址: Modern_Cpp_Practice.
代码持续更新,欢迎下载测试,喜欢的给个star!
本系列将长期更新,希望对您有帮助,本文的代码风格参考Google代码风格,希望对您有借鉴!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++11新特性:变长参数模板详解 的相关文章

  • 01背包问题(滚动数组实现的逻辑)

    package tttest public class mybetterbag public static void main String args int weight 61 1 3 4 int bagsize 61 4 int val
  • java递归实现辗转相除法

    public static int getres int a int b if b 61 0 return getres b a b return a
  • java 线索二叉树的构建

    public class test public static void main String args Node root 61 new Node 1 Node node2 61 new Node 2 Node node3 61 new
  • ubuntu下查看文件(夹)大小的命令

    记录下自己常用的查看文件夹和文件大小的命令 查看当前所处的文件夹的整个大小 xff08 不包括具体内容 xff0c 只看当前文件夹大小 xff09 span class token function du span sh 查看当前文件夹中各
  • git stash时出现xxx:needs merge问题

    项目需要git merge其他分支 xff0c 但由于本地也修改过 xff0c 所以希望先git stash后再merge xff0c 这时出现以下问题 xff1a xxx xxx xxx cpp xff1a needs merge 通过g
  • FFMPEG 之视频播放

    先看界面效果 xff0c 虽然有点low xff0c 但是效果实现了 一 实现原理 1 使用ffmpeg解码视频 2 然后使用libyuv播放解码的视频 二 实现 1 先看目录结构 2 ffmpeg编译以及引用 xff0c 在之前的篇章已经
  • 一步一步学CMake 之 VSCode+CMakeLists 调试 C++ 工程

    目录 1 插件推荐 2 文件准备 3 开始调试 一步一步学 CMake 系列文章 1 插件推荐 CMake CMake tools 2 文件准备 新建文件夹 xff1a TEST 新建文件 xff1a CMakeLists txt 内容如下
  • 51单片机使用8位重装定时器实现PWM输出同时实现DAC转换

    51单片机使用八位重装定时器实现PWM输出同时实现DAC转换 最近想要做一个数控电源 xff0c 打算使用51单片机实现电压和电流的闭环 xff0c 但是手头上的51单片机为STC89C51系列的单片机 xff0c 没有ADC采样功能 xf
  • 【MYSQL】分组之后获取每组最新的数据

    记录一次有点麻烦的sql 可以直接复制拿去测试 xff0c 一开始我也百度来着 xff0c 发现要么没法满足我的需求 xff0c 要么就连看下去的欲望都没有 建表测试demo xff1a span class token keyword C
  • C++ 指针中:指针数组 指向指针数组的指针 指向指针的指针

    指针数组 xff1a 存储指针的数组 pa n an array of pointers 注意这里 优先级高于 xff0c 因此pa是一个包含三个指针的数组 指向指针数组的指针 pd n pointers to an array of po
  • Flutter要被放弃了?别瞎传了!

    前言 Flutter 作为Google出品的一个新兴的跨平台移动客户端UI开发框架 xff0c 正在被越来越多的开发者和组织使用 xff0c 包括阿里的咸鱼 腾讯的微信等 今天 xff0c 我主要讲解Flutter中文本组件方面的Widge
  • (学习笔记)手把手教你学51单片机:定时器与数码管

    一 逻辑电路与逻辑运算 逻辑运算符 xff1a xff08 1 xff09 按变量整体值进行运算 xff1a 逻辑与 amp amp 逻辑或 xff08 xff09 逻辑非 xff08 xff01 xff09 xff08 2 xff09 按
  • (学习笔记)手把手教你学51单片机:中断与数码管动态显示

    一 c语言的数组 1 1数组的基本概念 数组是具有相同数据类型的有序数据的组合 xff0c 一般来讲数组定义后满足以下三个条件 xff1a xff08 1 xff09 具有相同的数据类型 xff08 2 xff09 具有相同的名字 xff0
  • KST-51:从999999开始的倒计时程序,只显示有效位

    此程序为手把手教你学51单片机的例程 例程中实现只显示有效位 xff08 高位0不显示 xff09 xff0c 实现了数码管稳定显示不抖动 for结合break 实现只显示有效位 switch结合i 实现数码管动态刷新 include lt
  • KST51单片机:通过中断实现矩阵按键的次数检测与消抖

    以Key4为例 xff0c 使用定时中断2ms进行消抖 xff0c 对连续8次 xff08 16ms xff09 的按键状态进行判断 如果全部为1则弹起 xff0c 将按键当前状态 xff08 Keysta xff09 为1 xff1b 全
  • 关于单片机蓝桥杯

    经大佬提醒 xff0c 已修改 芯片 xff1a IAP15F2K61S2 考核内容 xff1a LED 数码管 独立按键 矩阵按键 定时器 555 超声波 xff08 有基础 xff09 iic EEPROM ADC ds18b20 xf
  • NX nomachine 远程桌面配置

    其实它是Linux下一款类VNC的远控软件 xff0c 但据说安全性方面比VNC更好 xff0c 通过SSH协议加密进行传输的 而且传输是采用数据压缩技术 xff0c 传输更快 1 安装rpm包 安装顺序 xff1a root 64 loc
  • git 命令

    1 打patch xff08 git format patch xff09 git format patch HEAD 生成最近的1次commit的patch git format patch HEAD 生成最近的2次commit的patc
  • gitlab使用

    参考https blog csdn net justlpf article details 80681853 一 基本操作 1 登录 xff1a 2 修改密码 xff1a 二 项目管理 1 新建项目 2 编辑或删除项目 三 用户管理 xff
  • wsl不能启动解决方法

    wsl不能启动解决方法 admin 权限打开termianl 执行下面的命令 xff1a Dism Online Cleanup Image CheckHealth 是检查映像以查看是否有检测到损坏 Dism Online Cleanup

随机推荐