先看代码:
void print()
{
}
template <typename T,typename... Types> //...出现在这表示模板参数包
void print(const T& firstArg, const Types&... args) //...函数参数类型包
{
cout << firstArg << endl;
print(args...); //...函数参数包
}
int main()
{
print(7.5,"hello","what",42);
return 0;
}
运行结果:
这里重点是”…“,它就是一个所谓的包:
- 用于template parameters,就是template parameters pack(模板参数包)
- 用于function parameter types,就是function parameter types pack(函数参数类型包)
- 用于function parameters,就是function parameter pack(函数参数包)
注意,第一个”…”要加在typename后面,第二个”…”加在Types&后面,它表示可以传进任意个数的参数,且参数类型也可以是任意,这种机制主要能够帮助我们实现递归,如图中所示,
print(7.5,"hello","what",42);
print函数定义中,每次打印firstArg,其余的作为剩余参数由下代码进行递归
print(args...);
第一次打印7.5,余下3个参数,第二次打印”hello”,余下2个,最后一次打印”42″,余下0个参数,因此要注意最后的边界条件,所以要加上void print()的定义,否则编译出错。
以上的思想就是,把n个(任意个)参数分成1和n-1个,每次可以只处理1个,剩下的n-1个递归执行,很好地借用了递归思想从而极大地增大了代码的复用性。
variadic templates同样还能用于递归继承(以下是C++11中tuple(元组)的实现,它是把任意个数任意指定类型的东西形成的一个块或者对象的意思,可以给任意个数,任意类型),其继承关系如图右上继承关系可知,还是很优雅的。
注意,由于继承的关系,最先构造的是tuple<>,其次tuple<string>,最后是tuple<int,float,string>,因此定义顺序为(41,6.3,”nico”),而内存上的排布应当为(“nico”,6.3,41)。这一点通过以下代码测试可知(这里_Get_rest()等价于tail,_Myfirst等价于head):
通过观察_Myfirst的地址发现,”nico”地址最小,41对应地址最大,从而得到验证。
版权声明:本文为baidu_17611285原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。