您的位置:首页 > 编程语言 > C语言/C++

C++11新特性:可变参数模板

2016-07-25 19:27 232 查看
C++11新标准增加了可变参数模板,它让我们可以创建可接受可变数量的参数的模板函数和模板类。本文试着较为详尽地介绍可变参数模板函数。

首先,C++11提供了一个用省略号表示的元运算符(…),它可以让我们声明表示模板参数包的标识符。模板参数包其实是一个类型列表的省略(因为编写的时候不知道有多少参数)。同时,元运算符还能让我们声明能够表示函数参数包的标识符。函数参数包其实是一个值列表。

template <typename... Args>
void show_list1(Args... args) {
...
}


其中Args是一个模板参数包而args是一个函数参数包。

Args可以与任意数量的类型匹配。如

show_list1('s', 90, "sweet", 4.3);//参数包Args与函数调用中的参数类型匹配:char、int、const char *和double。
//而下面的代码指出args的类型为Args:
void show_list1(Args... args);


即是说,这意味着函数参数包args包含的值列表与模板参数包Args包含的类型列表匹配,无论是类型还是数量。在上面的示例中,args包含值’s’、90、“sweet”和4.3。

另外,上述可变参数模板show_list1()可以与下面的函数调用相匹配:

show_list1();
show_list1(99);
show_list1(88.7,"cat");
show_list1(2,4,6,8,"who do we",std::string("APPLE"));


就最后一个函数的调用而言,模板参数包Args包含类型int,int,int,int,const char*和std::string,而函数参数包args包含值2,4,6,8,”who do we”和std::string(“APPLE”)。

可变参数模板和递归

可变参数模板的一个用法就是和递归结合,从而相继对函数参数包中的每个参数进行操作。

核心的理念是,将函数参数包展开,对列表中的第一项进行处理,再将余下的内容传递给递归调用,以此类推,直到列表为空。与常规递归一样,确保递归将终止很重要。这里的技巧是将模板头改为如下所示:

template<typename T, typename... Args>
void show_list3(T value, Args... args)


show_list3()的第一个实参决定了T和value的值,而其他参数决定看了Args和args的值,因为他们的类型和值被打包在里面。

通过改进,可以让函数对第一个参数进行处理,如显示它。然后,可递归调用show_list3(),并以args… 的方式将其他实参传递给它。每次递归都将显示一个值,并传递缩短了列表,直到列表为空为止。

下面的程序简单的演示了可变模板函数的这个用法:

#include "iostream"
#include "string"
using std::cout;
using std::endl;
using std::string;
template <typename T>
void show_list(T value) {   //当args包只有一项时,将调用这个版本
cout << value << endl;
}
//也可以声明这样一个函数来结束递归:void show_list() {},当args包为0时,将调用这个版本以结束递归

template <typename T, typename... Args>
void show_list(T value, Args... args) {
cout << value << ", ";
show_list(args...);
}

int main() {
int n = 14;
double x = 2.4;
string mr = "something";
show_list(x * x, n, '!', 7, mr);
return 0;
}


当然,可变参数模板的引用形式为:

template<typename... Args>
show_list(const Args&... args);     //这将对每个函数参数应用const模式,如const int & n
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息