可变参模板:(Variadic Templates):允许模板中含有0个到任意个模板参数,在语法上也和传统模板不太一样,多了一个…
一:可变参函数模板
<1>简单范例
值得注意的内容:
1>我们一般把这个args称为一包或者一堆参数,而且这些参数的类型可以各不相同;
我们理解T这种类型的时候,不能把他理解成一个类型,你要理解成0到多个不同的类型,那自然,对应的参数args也应该是多个不同类型的参数;
2>这一包参数中可以容纳0到多个模板参数,而且这些模板参数可以为任意的类型;
3>大家注意把名字理顺一下:
T后边带了…,所以,我们称呼T:可变参类型;这个东西看起来是一个类型名,实际上里边包含的是0到多个不同的类型(一包类型);
args:可变形参,既然T代表的是一包类型,那显然args代表的就一包形参;
4>在具体函数形参中,&的位置,出现在了类型名的后边。
template <typename... T>
void myfunct1(T... args) //T:一包类型 ,args:一包形参
{
cout << sizeof...(args) << endl; //sizeof...可变参数量
cout << sizeof...(T) << endl;
}
int main()
{
myfunct1();
myfunct1(10, 20);
myfunct1(10, 25.8, "abc");
return 0;
}
<2>参数包的展开:展开套路比较固定,一般都是用递归函数的方式来展开参数;
要求我们在代码编写中,有一个参数包展开函数,和一个同名的递归终止函数,我们就是通过这两个函数把参数包展开的;
//递归终止 函数
void myfunct2()
{
cout << "参数包展开时执行了递归终止函数myfunc2()..." << endl;
}
template <typename T, typename...U>
void myfunct2(const T& firstarg, const U&... otherargs) //一个参数,一包参数,这种可变参函数模板写法最适合参数包的展开
{
//cout << sizeof...(otherargs) << endl;
cout << "收到的参数值为:" << firstarg << endl;
myfunct2(otherargs...); //递归调用,注意写法...
}
int main()
{
myfunct2(10);
myfunct2(10, "abc", 12.7);
myfunct2("abc", 12.7);
myfunct2(12.7);
myfunct2();
return 0;
}
二:可变参类模板
允许模板定义中含有0到任意个模板参数;
<1>通过递归继承方式展开参数包
template<typename... Args>
class MyClassST //主模板
{
public:
MyClassST()
{
printf("MyclassST::MyclassST()泛化版本执行了,this = %p \n", this);
}
};
template<> class MyClassST<> //0个模板参数的特化版本
{
public:
MyClassST()
{
printf("myclasst<>::myclasst()特殊的特化版本执行了,this = %p\n", this);
}
};
template<typename First, typename... Others>
class MyClassST<First, Others...> : private MyClassST<Others...>
{
public:
MyClassST() : m_f(0)
{
cout << "-------------------begin----------------" << endl;
printf("MyclassST::MyclassST()偏特化版本执行了,this = %p, sizeof...(Others) = %zd \n", this, sizeof...(Others));
cout << "m_f = " << m_f << endl;
cout << "-------------------end------------------" << endl;
}
MyClassST(First parf, Others... paro) : m_f(parf), MyClassST<Others...>(paro...)
{
cout << "-------------------begin----------------" << endl;
printf("MyclassST(First parf, Others... paro)执行了,this = %p \n", this);
cout << "m_f = " << m_f << endl;
cout << "-------------------end------------------" << endl;
}
public:
First m_f;
//MyClassST
};
int main()
{
MyClassST<int, float, double> myc(12, 13.5, 23.7);
//范例取材:标准库中的tuple(元组)
return 0;
}
<2>通过递归组合方式展开参数包
template<typename... Args>
class MyClassST //主模板
{
public:
MyClassST()
{
printf("MyclassST::MyclassST()泛化版本执行了,this = %p \n", this);
}
};
template<> class MyClassST<> //0个模板参数的特化版本
{
public:
MyClassST()
{
printf("myclasst<>::myclasst()特殊的特化版本执行了,this = %p\n", this);
}
};
template<typename First, typename... Others>
class MyClassST<First, Others...>
{
public:
MyClassST() : m_f(0)
{
cout << "-------------------begin----------------" << endl;
printf("MyclassST::MyclassST()偏特化版本执行了,this = %p, sizeof...(Others) = %zd \n", this, sizeof...(Others));
cout << "m_f = " << m_f << endl;
cout << "-------------------end------------------" << endl;
}
MyClassST(First parf, Others... paro) : m_f(parf), m_o(paro...)
{
cout << "-------------------begin----------------" << endl;
printf("MyclassST(First parf, Others... paro)执行了,this = %p \n", this);
cout << "m_f = " << m_f << endl;
cout << "-------------------end------------------" << endl;
}
public:
First m_f;
MyClassST<Others...> m_o;
};
int main()
{
MyClassST<int, float, double> myc(12, 13.5, 23.7);
//范例取材:标准库中的tuple(元组)
return 0;
}
<3>通过tuple和递归调用展开参数包
template<int mycount, int mymaxcount, typename... T>
class MyClassST2
{
public:
static void mysfunc(const tuple<T...>& t)
{
cout << "value = " << get<mycount>(t) << endl;
MyClassST2<mycount + 1, mymaxcount, T...>::mysfunc(t);
};
};
template<int mymaxcount, typename... T>
class MyClassST2<mymaxcount, mymaxcount, T...>
{
public:
static void mysfunc(const tuple<T...>& t)
{
};
};
template<typename... T>
void myfunctuple(const tuple<T...>& t)
{
MyClassST2<0, sizeof...(T), T...>::mysfunc(t);
}
int main()
{
tuple<float, int, int> mytuple(12.5f, 100, 52);
myfunctuple(mytuple);
return 0;
}
三:模板模板参数
有点难,暂时跳过。