C++基础知识—可变参数函数模板和类模板
一、可变参数函数模板
代码示例:
#include <iostream>
using namespace std;
void myfunct2()
{
cout << "参数包展开时执行了递归终止函数myfunc2()" << endl;
}
template <typename T, typename...U>
void myfunct2(const T& firstarg, const U&...otherargs)
{
cout << "收到的参数值为:" << firstarg << endl;
myfunct2(otherargs...);
}
int main()
{
myfunct2(10, "abc", 12, 7);
return 0;
}
输出结果:
收到的参数值为:10
收到的参数值为:abc
收到的参数值为:12
收到的参数值为:7
参数包展开时执行了递归终止函数myfunc2()
二、可变参数类模板
1、递归继承展开参数包
代码示例:
#include <iostream>
using namespace std;
template<typename...Args>
class myclasst
{
public:
myclasst()
{
cout << "myclasst::myclasst()泛化版本执行了,this = " << this << endl;
}
};
// 也可以用带零个模板参数的泛化的实例化
#if 1
template<>
class myclasst<>
{
public:
myclasst()
{
cout << "myclasst::myclasst()特殊的特化版本执行了,this = " << this << endl;
}
};
#endif
template<typename First, typename...Others>
class myclasst<First, Others...> :private myclasst<Others...> //偏特化
{
public:
myclasst() : m_i(0)
{
cout << "myclasst::myclasst()偏特化版本执行了,this = " << this << "sizeof...(Others)=" << sizeof...(Others) << endl;
}
myclasst(First parf, Others...paro) :m_i(parf), myclasst<Others...>(paro...)
{
cout<<"------------------begin-------------------"<<endl;
cout<<"myclasst::myclasst(parf,...paro)执行了,this = "<<this<<endl;
cout<<"m_i = " <<m_i<<endl;
cout<<"-------------------end--------------------"<<endl<<endl;
}
First m_i;
};
int main()
{
myclasst<int, float, double>myc(12,13.5,23);
return 0;
}
输出结果:
myclasst::myclasst()特殊的特化版本执行了,this = 0055F9B4
------------------begin-------------------
myclasst::myclasst(parf,...paro)执行了,this = 0055F9B4
m_i = 23
-------------------end--------------------
------------------begin-------------------
myclasst::myclasst(parf,...paro)执行了,this = 0055F9B4
m_i = 13.5
-------------------end--------------------
------------------begin-------------------
myclasst::myclasst(parf,...paro)执行了,this = 0055F9B4
m_i = 12
-------------------end--------------------
2、递归组合展开参数包
代码示例:
#include <iostream>
using namespace std;
template<typename...Args>
class myclasst
{
public:
myclasst()
{
cout << "myclasst::myclasst()泛化版本执行了,this = " << this << endl;
}
};
// 也可以用带零个模板参数的泛化的实例化
#if 1
template<>
class myclasst<>
{
public:
myclasst()
{
cout << "myclasst::myclasst()特殊的特化版本执行了,this = " << this << endl;
}
};
#endif
template<typename First, typename...Others>
class myclasst<First, Others...> /*:private myclasst<Others...> //偏特化*/
{
public:
myclasst() : m_i(0)
{
cout << "myclasst::myclasst()偏特化版本执行了,this = " << this << "sizeof...(Others)=" << sizeof...(Others) << endl;
}
myclasst(First parf, Others...paro) :m_i(parf), m_o(paro...) /*myclasst<Others...>(paro...)*/
{
cout << "------------------begin-------------------" << endl;
cout << "myclasst::myclasst(parf,...paro)执行了,this = " << this << endl;
cout << "m_i = " << m_i << endl;
cout << "-------------------end--------------------" << endl << endl;
}
First m_i;
myclasst<Others...> m_o;
};
int main()
{
myclasst<int, float, double>myc(12, 13.5, 23);
return 0;
}
输出结果:
myclasst::myclasst()特殊的特化版本执行了,this = 00DBFAE8
------------------begin-------------------
myclasst::myclasst(parf,...paro)执行了,this = 00DBFAE0
m_i = 23
-------------------end--------------------
------------------begin-------------------
myclasst::myclasst(parf,...paro)执行了,this = 00DBFAD8
m_i = 13.5
-------------------end--------------------
------------------begin-------------------
myclasst::myclasst(parf,...paro)执行了,this = 00DBFAD0
m_i = 12
-------------------end--------------------
3、tuple和递归调用展开参数包
代码示例:
#include <iostream>
#include <tuple>
using namespace std;
// 类模板得泛化版本
template<int mycount, int mymaxcount, typename...T> //mycount用于统计,从0开始,mymaxcount表示参数数量,可以用sizeof...获得
class myclasst2
{
public:
static void mysfunc(const tuple<T...>& t)
{
cout << "value = " << get<mycount>(t) << endl; //可以把每个参数取出来并输出
myclasst2<mycount + 1, mymaxcount, T...>::mysfunc(t); //计算每次+1,这里时递归调用自己;
}
};
// 偏特化版本,用于结束递归调用
template<int mymaxcount, typename...T>
class myclasst2<mymaxcount, mymaxcount, T...>
{
public:
static void mysfunc(const tuple<T...>& t)
{
}
};
template<typename...T>
void myfunctuple(const tuple<T...>& t) // 可变参函数模板
{
myclasst2<0, sizeof...(T), T...>::mysfunc(t); // 第一个参数为0,从0开始计数;
}
#endif
int main()
{
tuple <float, int, int>mytuple(12.5f, 100, 52);
myfunctuple(mytuple);
return 0;
}
输出结果为:
value = 12.5
value = 100
value = 52
总结
1、可变参函数模板用展开参数包
2、可变参类模板用展开参数包
3、tuple和递归调用展开参数包