系列文章目录
C++11&14新标准——Variadic templates(数量不定的模板参数)
1. 定义
Variadic templates用于表示数量不确定的参数,如果要使用这个这个功能,应该先在template处定义,即:
template<typename T,typename... Types>
至此就可以使用任意类型、任意数量的参数。在函数参数当中想要使用,格式为:
void print(const T& firstArg,const Types&... args)
这个函数表达的意思是接收的第一个参数必须为const T&,后面可以接收任意数量任意类型的参数。在函数中想要使用这些数量不定的参数,具体格式为:
arg...
sizeof...(args) // 可以用sizeof来获得参数的个数
…的具体含义就是一个pack(包)
2. 相关应用
(1)函数的递归调用
我们定义了三个hash_val函数,分别是:
1.inline size_t hash_val(const Types&... args)
2.inline void hash_val(size_t& seed,const T& val,const Types&... args)
3.inline void hash_val(size_t& seed,const T& val)
现在要调用hash_val函数,该调用哪一个版本的呢?就要根据参数列表来判断:
1.第一次调用,由于第一个参数的类型是const Customer& c,所以只能调用版本1的hash_val。
2.版本1中继续调用hash_val,此时的参数列表为hash_val(seed,args…),此时既可以调用版本1,也可以调用版本2,但我们应该调用特化版本——即最符合参数列表类型的版本,所以这时候调用版本2的hash_val。
3.版本2中会从arg…中取出第一个参数进行处理,然后继续调用hash_val,此时调用的为版本2,即递归调用(调用自己),但递归调用需要有一个边界,不能无限递归下去,所以设计了版本3,但arg…个数为0时,调用版本3,结束递归。
(2)类的递归构造
Variadic templates可以很方便的实现模板构造。首先构造两个模板类:
template<typename... Value> class tuple;//参数完全不定
template<> class tuple {};//无参数
然后构造一个特化的模板类继承自己:
template<typename Head,typename... Tail>
class tuple<Head,Tail...>:private tuple<Tail...>
可以看到,在这个类的构造函数中,第一个参数赋值给类中的元素,剩下的参数全部对继承的模板类进行构造,而继承的类将重复这个构造过程,直到参数为0时,构造无参数版本的类终止递归,最终实现的是一个逐层嵌套的效果。
tuple每一层都有一个定义的head,为第一个参数。