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

 更新时间:2021年08月25日 16:08:02   作者:Codebowl  
本文主要介绍了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 变长参数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C/C++读写文本文件、二进制文件的方法

    C/C++读写文本文件、二进制文件的方法

    今天小编就为大家分享一篇C/C++读写文本文件、二进制文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 利用C语言实现任务调度的示例代码

    利用C语言实现任务调度的示例代码

    这篇文章主要为大家详细介绍了如何利用纯C语言实现任务调度(可用于STM32、C51等单片机),文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-04-04
  • C语言版五子棋游戏的实现代码

    C语言版五子棋游戏的实现代码

    这篇文章主要为大家详细介绍了C语言版五子棋游戏的实现代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C++破坏MBR的代码

    C++破坏MBR的代码

    这篇文章主要介绍了C++破坏MBR的代码,涉及到对硬盘的主引导记录的破坏性操作,具有一定的参考价值,需要的朋友可以参考下
    2014-10-10
  • C语言实现顺序循环队列实例

    C语言实现顺序循环队列实例

    大家好,本篇文章主要讲的是C语言实现顺序循环队列实例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • vsCode配置import@路径提示的实现步骤

    vsCode配置import@路径提示的实现步骤

    在导入文件设置路径的时候方便了很多,本文主要介绍了vsCode配置import@路径提示的实现步骤,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • C语言实现影院管理系统程序设计

    C语言实现影院管理系统程序设计

    这篇文章主要为大家详细介绍了C语言实现影院管理系统程序设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言中函数指针与软件设计经验总结

    C语言中函数指针与软件设计经验总结

    今天小编就为大家分享一篇关于C语言中函数指针与软件设计经验总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • C语言实现循环单链表的示例代码

    C语言实现循环单链表的示例代码

    这篇文章主要给大家详细介绍了C语言如何实现循环单链表,文章通过代码示例讲解的非常详细,对我们的学习或工作有一定的参考价值,感兴趣的小伙伴跟着小编一起来看看吧
    2023-08-08
  • C++中的四种类型转换

    C++中的四种类型转换

    类型转换有c风格的,当然还有c++风格的。c风格的转换的格式很简单(TYPE)EXPRESSION,但是c风格的类型转换有不少的缺点,有的时候用c风格的转换是不合适的,因为它可以在任意类型之间转换,
    2015-08-08

最新评论