前言C++的一个新特性——可变模板参数(variadictemplates)是C++最强大的新特性之一,它对参数进行了高度泛化。它可以表示0到任意数量的任意类型的参数。与C++98/03相比,类模板和函数模板只能包含固定数量的模板参数,可变模板参数无疑是一个巨大的进步。但是,由于可变模板参数比较抽象,需要一定的技巧才能使用,这也是C++中最难理解和掌握的特性之一。可变模板参数虽然很难掌握,但却是C++11中最有趣的特性。本文希望带领读者由浅入深地了解和掌握这一特性。同时会通过一些例子来展示变量参数模板的一些用法。可变参数模板的扩展可变参数模板的语义与普通模板相同,只是写法略有不同。声明可变参数模板时,需要在typename或class后面加上省略号“...”。比如我们经常这样声明一个可变模板参数:templatetemplatevoidf(T...args);省略号的作用:1.声明一个参数包T...args,可以包含0到任意数量的模板参数;2.在模板定义的右侧,参数包可以扩展为单独的参数。带省略号的参数称为“参数包”,包含0到N(N>=0)个模板参数。我们无法直接获取参数包args中的每个参数,只能通过扩展参数包来获取参数包中的每个参数。这是使用可变模板参数的一个主要特点,也是最大的难点,即如何扩展可变模板参数。可变模板参数分类:1.可变模板参数函数2.可变模板参数类打印可变模板参数函数的参数个数#include#includeusingnamespacestd;templatevoidprint(输入...数据){cout<usingnamespacestd;//递归终止函数voidprint(){cout<<"递归终止函数"<voidprint(Tdata,Type...exData){cout<usingnamespacestd;//递归终止函数templateTypesum(Typet){returnt;}//展开函数templateTsum(Ta,输入...b){returna+sum(b...);}intmain(){cout<usingnamespacestd;//递归终止函数..Type>voidprint(Type...exData){intarray[]={(print(exData),0)...};}intmain(){print(1,2,3);cout<classinitializer_list;下面简单介绍一下initializer_list。一个initializer_list出现在以下两种情况时是自动构造的:初始化时用花括号初始化,自动构造。包括函数调用和赋值,当遇到for(initializer:list)时,list会自动构造成一个initializer_list对象,也就是说initializer_list对象只能用大括号{}来初始化。复制initializer_list对象不会复制其元素。这实际上只是一个引用。并且里面的所有元素都是const。下面的例子可以帮助我们更好的理解如何使用initializer_list::v(l){cout<<"constructedwitha"<l){v.insert(v.end(),l.begin(),l.end());}pairc_arr()const{return{&v[0],v.size()};}};templatevoidtemplated_fn(Targ){for(autoa:arg)cout<s={1,2,3,4,5};s。append({6,7,8});for(auton:s.v)cout<<''<>({7,8,9});templated_fn>({3,5,7});return0;}变量模板参数类std::tuple是一个变量模板类templateclasstuplee;这个可变参数模板类可以携带任意数量的任意类型的模板参数:tupletp1=std::make_tuple(1);tupletp2=std::make_tuple(1,2.5);tupletp3=std::make_tuple(1,2.5,"");可变参数模板的模板参数个数可以为0,所以下面的定义也是合法的:tuple<>tp;可变参数模板类的参数包的展开方式与可变参数模板函数不同。可变参数模板类的参数包的扩展需要通过模板特化和继承来扩展。模板函数更复杂模板偏特化和递归方式扩展参数包基本可变参数模板类//前向声明templatestructSum;//基本定义templatestructSum{enum{value=Sum::value+Sum::value};};//递归终止模板structSum{enum{value=sizeof(Last)};};intmain(){cout<::value<structIndexSeq{};//继承方法,开始扩展参数包templatestructMakeIndexes:MakeIndexes{};//模板特化,条件为终止扩展参数包templatestructMakeIndexes<0,Indexes...>{typedefIndexSeqtype;};intmain(){usingT=MakeIndexes<3>::type;cout<usingnamespacestd;templateT*Instance(精...精gs){returnnewT(args...);}classA{public:A(inta):a(a){}A(inta,intb):a(a){}A(inta,intb,stringc):a(a){}voidprint(){cout<(1);B*pb=Instance(1,2);;pa->print();pb->print();pa=Instance(100,2);pa->print();pa=Instance(100,2,"LoveYou");pa->print();return0;}默认模板classMyDelegate{public:MyDelegate(T*t,R(T::*f)(Args...)):m_t(t),m_f(f){}Roperator()(Args...args){return(m_t->*m_f)(args...);}//Roperator()(Args&&...args);//{//return(m_t->*m_f)(std::forward(args)...);//}private:T*m_t;R(T::*m_f)(Args..);};templateMyDelegateCreateDelegate(T*t,R(T::*f)(Args...)){返回MyDelegate(t,f);}structA{voidFun(inti){cout<