我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++11新特性之变长参数模板详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++11新特性之变长参数模板详解

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);

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

如何解参数包

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

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

sizeof()获得函数参数个数

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


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

递归模板函数

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

printf 会不断地递归调用自身:函数参数包 args... 在调用时, 会被模板类别匹配分离为 T value和 Args... 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.

到此这篇关于C++11新特性之变长参数模板详解的文章就介绍到这了,更多相关C++11 变长参数内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++11新特性之变长参数模板详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++11中的变长模板的示例详解

C++中的变长模板真的是又臭又长,晦涩难懂,但是确实有些STL库就是这么写的。本文就来和大家聊聊C++11中这些变长模块的使用,需要的可以参考一下
2023-02-06

C++新标准难点解析之什么是可变模板参数

本篇内容介绍了“C++新标准难点解析之什么是可变模板参数”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 前言C++的新特性--可变模版参数(
2023-06-15

C++ 函数模板详解:揭秘编译期可变性的奥秘

函数模板提供了编译器生成的编译期可变函数,提高代码效率和通用性。语法: template t sum(t a, t b)编译期可变性: 类型参数在调用时生成新函数版本。实际案例:通用排序算法类型安全运算符重载元编程优势:代码重用通用性编译时
C++ 函数模板详解:揭秘编译期可变性的奥秘
2024-04-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录