一、基本语法
声明一个带有可变参数个数的模板的语法如下所示:
template<typename ...Element> class tuple;
tuple<int, string> a; // use it like this
在模板参数 Element 左边出现省略号 ... ,就是表示 Element 是一个模板参数包(template type parameter pack).parameter pack(参数包)是新引入 C++ 中的概念,比如在这个例子中,Element 表示是一连串任意的参数打成的一个包.比如第2行中,Element 就是 int, string这个参数的合集.不仅“类型”的模板参数(也就是typename定义的参数)可以这样做,非类型的模板参数也可以这样做.比如下面这个例子:
template<typename T, unsigned PrimaryDimesion, unsigned...Dimesions>
class array { /**/ };
array<double, 3, 3> rotation_matrix; //3x3 ratiation matrix
现在我们知道parameter pack了,怎么在程序中真正具体地去处理打包进来的“任意个数”的参数呢?
原来以为,编译器会提供一些像get_param<1>(Element) 之类的内建的“参数抽取函数”给程序员使用,结果不是!!
看来我的思路还是太“过程式了”.其实 C++11 用的是 unpack 和类似函数重载似的“模板特化”来抽取参数的.
这是应用 variadic tempate 最“坑爹”的部分,因为它要求对“递归”和“人肉代码展开”有一定的功力啊.还是看例子吧:
template<typename... Elements> class tuple;
template<typename Head, typename... Tail>
class tuple<Head, Tail...> : private tuple<Tail...>
//这里应该算模板的特化,可变参数的模板特化时参数个数可能与声明时的模板参数个数不一致,因为是可变参数模板所以是可以编译通过,普通模板如此特化编译是通不过的.
{
Head head;
public:
/* implementation */
};
template<>
class tuple<>
{
/* zero-tuple implementation */
};
第1行声明了一个可以对应任意参数的tuple类,第2行到7行声明了这个类的一个部分特化,注意,这就是抽取参数的典型方法了.给个图还是最方便用来理解的:
只说明一下针对 parameter pack 相对的另一个概念,模板参数后面带省略号 ... 就是一个解包(unpack),会把这个参数所表示的参数列表解开后去匹配新的模板,或是进行模板展开.