本部分包括的内容为Variadic Templates(可变模板参数),这部分似乎是个概述,我看到后面有好几节课也是这个主题。
一、概述
void print()
{
}
template <typename T, typename... Types> //这里的...是关键字的一部分
void print(const T& firstArg, const Types&... args) //这里的...要写在自定义类型Types后面
{
cout << firstArg << endl;
print(args...); //这里的...要写在变量args后面
}
1. 注意三种不同的...的应用环境,这些都是语法规则,所以记住即可。
2. 还要注意的是,在可变模板参数内部可以使用sizeof...(args)得到实参的个数。
3. 如果同时定义了:
template <typename... Types>
void print(const Types&... args)
{/*......*/}
那么这两个定义会优先调用哪个?换句话说,哪个定义更加泛化,哪个更加特化?这个侯捷老师说以后会做解释
(更新:这个更加泛化,所以会调用之前定义的更特化的版本)
二、Variadic Templates的两个应用
1. 实现函数的递归调用
举了一个unordered容器中hash函数的计算例子:
class CustomerHash{
public:
std::size_t operator() (const Customer& c) const {
return hash_val(c.fname, c.lname, c.no);
}
};
template <typename T, typename... Types>
inline void hash_val(size_t& seed, const T& val, const Types&... args){
hash_combine(seed, val);
hash_val(seed, args);
}
template <typename... Types>
inline size_t hash_val(const Types&... args){
size_t seed = 0;
hash_val(seed, args...);
return seed;
}
template <typename T>
inline void hash_val(size_t& seed, const T& val){
hash_conbine(seed, val);
}
本质上和概述里的例子一样,都是利用可变模板参数的函数递归操作,这里就不多做解释了。
2. 实现递归继承
这里举了一个tuple的实现的例子:
template <typename... Values> class tuple;
template <> class tuple<> {};
template <typename Head, typename... Tail>
class tuple<Head, Tail...>
: private tuple<Tail...> //注意这里的私有继承
{
typedef tuple<Tail...> inherited;
public:
tuple() {}
tuple(Head v, Tail... vtail)
:m_head(v), inherited(vtail...) {}
Head head() { return m_head; }
inherited& tail() { return *this; } //这里涉及派生类到基类的类型转换
protected:
Head m_head;
};
PPT里解释得很清楚: