C++11之前,类模板和函数模板只能含有固定数量的模板参数,C++11增强了模板功能,允许模板定义中包含0到任意个模板参数,这就是可变参数模板。
可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,申明可变参数模板时需要在typename或class后面带上省略号 “…”
一个可变参数模板函数的定义如下:
templatevoid f(T... args) { cout< 1.2 参数包的展开 1.2.1 递归方式展开 通过递归方式展开函数包,需要提供一个参数包展开函数和一个终止递归函数。
#include1.2.2 非递归方式展开using namespace std; // 终止递归函数 void print() { cout << "empty" << endl; } // 展开函数 template void print(T head,Args... rest) { cout << "parameter "< print(1, 2, 3, 4); return 0; } 递归函数展开参数包是一种标准做法,也比较好理解,但也有一个缺点,就是必须有一个重载的递归终止函数,即必须有一个同名的终止函数来终止递归,这样会感觉稍有不便。其实还有一种方法可以不通过递归方式来展开参数包。比如:
#include2 可变参数模板类 2.1 可变参数模板类的定义using namespace std; template void printarg(T t) { cout << t << endl; } template void expand(Args... args) { int arr[] = { (printarg(args),0)... }; } int main() { expand(1, 2, 3, 4); return 0; } 可变参数模板类是一个带可变模板参数的模板类,第1章中介绍的std::tuple就是一个可变模板类,它的定义如下:
templateclass tuple; 这个可变参数模板类可以携带任意类型任意个数的模板参数:
std::tupletp1=std::make_tuple(1); std::tuple tp2=std::std::make_tuple(1, 2.5); std::tuple tp2=std::std::make_tuple(1, 2.5,"test"); 可变参数模板的模板参数个数可以为0,所以下面的定义也是合法的:
std::tuple<> tp;2.2 参数包的展开 2.2.1 模板递归和特化方式展开参数包可变参数模板类的展开一般需要定义2~3个类,包括类声明和特化的模板类。如下方式定义了一个基本的可变参数模板类:
templatestructSum; template struct Sum { enum { value = Sum ::value +Sum ::value); } template struct Sum { enum { value = sizeof (Last)}; } 这个sum类的作用是在编译期计算出参数包中参数类型的size之和,通过sum
::value就可以获取这3个类型的size之和为14。这是一个简单的通过可变参数模板类计算的例子,可以看到一个基本的可变参数模板应用类由三部分组成:
1> 第一部分:templatestruct sum 它是前向声明,声明这个类是一个可变参数模板类
2> 第二部分是类的定义:
templatestruct sum { enum { value = Sum ::value +Sum ::value); } 它定义了一个部分展开的可变参数模板类,告诉编译器如何递归展开参数包。
3> 第三部分是特化的递归终止类:
templatestruct Sum { enum { value = sizeof (Last)}; } 上面的这种3段式的定义也可以改为两段式,去掉前向声明:
template2.2.2 继承方式展开参数包struct sum { enum { value = Sum ::vlue+Sum< Rest...>::value); }; template { enum { value = sizeof(Last); }; } 除了通过模板递归和模板特化的方式展开,还有另外一种方式:通过继承和特化的方式展开。下面的例子就是通过继承的方式去展开参数包
//整数序列的定义 templatestruct IndexSeq{}; //继承方式,开始展开参数包 template struct MakeIndexes : MakeIndexes {}; //模板特化,终止展开参数包的条件 template struct MakeIndexes<0, Indexes...> { typedef IndexSeq type; }; int main() { using T = MakeIndexes<3>::type; cout< 最终输出的类型是struct IndexSeq<0, 1, 2>


![[C++11 模板的改进] --- 可变参数模板 [C++11 模板的改进] --- 可变参数模板](http://www.mshxw.com/aiimages/31/951789.png)
