1. auto和decltype
2. 可变参数模板
定义:对模板的参数高度泛化,可以表示0到任意个、任意类型的参数
- 函数参数包
template<typename... A> class Car;
//typename... 是一个模板参数包,可以这样实例化模板
Car<int ,char> car;
- 包扩展
template<typename... A>
class Car{
};
template<typename... A>
class BMW:public Car<A...>{
};
BMW<int,char> car;
//A...称之为包扩展(pack extension),包扩展是可以传递的
- 特性
template<typename... A>
void f(A... args)
{
cout<<sizeof...(args);//打印变参的个数
}
f();//输出0
f(1,2);//输出2
f(1,2,"");//输出3
- 1 可变参数模板通过递归展开参数包
//需要一个终止函数
void print(){
cout<<"empty"<<endl;
}
template<class T,class... Args>
void print(T head,Args... rest){
cout<<"parameter"<<head;
print(rest);
}
template<class T>
T sum(T t){
return t;
}
template<class T,class... Args>
T sum(T t,Args... rest){
return first+sum<T>(rest);
}
- 2 逗号表达式展开参数包
逗号表达式:b=(a=b,c)//最后的结果是a=b,b=c
在这里插入代码片template <class T>
void printarg(T t)
{
cout << t << endl;
}
template <class ...Args>
void expand(Args... args)
{
int arr[] = {(printarg(args), 0)...};
}
expand(1,2,3,4);
/*
//在执行expand的时候,会构造一个长度为sizeof...(args)的数组,因为有逗号表达式,在构造的时候会调用printarg(args).
//{(printarg(args), 0)...}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc... )
*/
- 将函数作为参数,支持lambda表达式
template<class F, class... Args>void expand(const F& f, Args&&...args)
{
//这里用到了完美转发,关于完美转发,参考:四行代码看右值引用
initializer_list<int>{(f(std::forward< Args>(args)),0)...};
}
expand([](int i){cout<<i<<endl;}, 1,2,3);
上面的例子将打印出每个参数,这里如果再使用C++14的新特性泛型lambda表达式的话,可以写更泛化的lambda表达式了:
expand([](auto i){cout<<i<<endl;}, 1,2.0,”test”);
参考:四行代码看右值引用
参考:泛化之美–C++11可变模版参数的妙用