函数模版中含有可变参数
假设我们现在函数模版不确定有多少个参数,也不确定参数的类型,我们就可以在函数模版中使用可变参数
函数模版中有可变参数的写法
如何隔将函数模版中可变参数解析出来
//函数模版中含有可变参数
//假设我们现在函数模版不确定有多少个参数,0-N个,也不确定参数的类型,我们就可以在函数模版中使用可变参数//函数模版中有可变参数的写法,注意返回类型需要时确定的,如果返回类型是T 会报错template<typename ...T>
//T func113(T...args) {//build error ,返回类型如果是T 就会报错
int func113(T&...args) {cout << sizeof...(T) << endl;cout << sizeof...(args) << endl;return 0;
}//递归结束的条件,当没有参数的时候,就递归结束,
//实际测试中发现,如果func114()写在void func114(T&...args)后面,就不会调用到func114()这个函数。
void func114() {cout << "递归结束" << endl;}//如何将函数模版中可变参数解析出来呢?一般都是将借助递归方式来展开参数
template<typename ...T>
void func114(T&...args) {cout << sizeof...(T) << endl;cout << sizeof...(args) << endl;
}template<typename T , typename...U>
void func114(T& first, U&...otherargs) {cout << first << endl;func114(otherargs...);}void main() {int a = 90;double b = 89.9;func113(a, b);cout << "......" << endl;string s = "nihao";double d = 999.989;int c = 8765678;func114(s, d,c);
}
类模版中含有可变参数
解析方法一,使用继承自己的方式
//一般需要 private 继承自己,以方便展开包处理
template<typename ...T>
class Teacher115 {};//注意写法
template<typename First,typename ...Otherargs>
class Teacher115<First,Otherargs...> : private Teacher115<Otherargs...> {
public://在构造函数中,递归的调用自己Teacher115(First fir, Otherargs ...oth):Teacher115<Otherargs...>(oth...),m_i(fir) {cout << "m_i = " << m_i << endl;}First m_i;
};//然后最好写上父类0个参数的调用
template<>
class Teacher115<> {
public:Teacher115() {cout<<"没有参数的构造函数"<<endl;}
};
void main() {Teacher115<string, int, double> teacher115("nihao", 89, 76878.89);cout << "断点在这里" << endl;
}
解析方法二 ,使用包含自己的方式
//组合方式 :一般需要包含自己,以方便展开包处理
template<typename ...T>
class Teacher116{};//注意写法
template<typename First,typename ...Otherargs>
class Teacher116<First,Otherargs...> {
public://在构造函数中,组合自己的变量赋值,注意方式Teacher116(First fir, Otherargs ...oth):m_i(fir) ,m_o(oth...){cout << "m_i = " << m_i << endl;}First m_i;Teacher116<Otherargs...> m_o;//要组合一个自己
};//然后最好写上父类0个参数的调用
template<>
class Teacher116<> {
public:Teacher116() {cout<<"没有参数的构造函数"<<endl;}
};
void main() {Teacher116<string, int, double> teacher116(string("nigggghao"), 789, 787778.8);cout << "断点在这里" << endl;
}
解析方法三:通过tuple 和递归调用展开参数包
这种展开参数包的方式需要写类的特化版本,有一定的难度。
实现思路是:
有一个计数器,从0开始,每处理一个参数,计数器+1,一直到把所有的参数都处理完。最后搞一个模版偏特化,作为递归调用结束。
学习 tuple 的使用:
学习将函数模版中的参数,借助 tuple 和 类模版参数的意义解析
//学习tuple类的使用
//tuple类的功能是将不同的类型整合在一起
void main119() {tuple<float, int, string> mytu(12.5, 89, "nihao");//获取tuple类的数据cout << get<0>(mytu) << endl;cout << get<1>(mytu) << endl;cout << get<2>(mytu) << endl;}//泛化版本
template<int nowcount, int maxcount, typename...T>
class Teacher118 {
public:static void staticteacher118fun(const tuple<T...> &t) {cout << "value = " << get<nowcount>(t) << endl;Teacher118<nowcount + 1, maxcount, T...>::staticteacher118fun(t);}
};//特化版本,用于结束递归调用,注意这块的写法:class Teacher118<maxcount, maxcount,T...> 也就是说;当第一个参数和第二个参数一样的时候,就会走到这个特化版本
template<int maxcount, typename...T>
class Teacher118<maxcount, maxcount,T...> {
public:static void staticteacher118fun(const tuple<T...> &t) {cout << "循环结束了 " << endl;}
};template<typename...T>
void myfunc119(const tuple<T...> &t) {Teacher118<0, sizeof...(T), T...>::staticteacher118fun(t);
}
void main() {//先使用 tuple 将所有的参数都集合起来tuple<float, int, string> mytu(1222.5, 839, "n23ihao");myfunc119(mytu);// value = 1222.5// value = 839// value = n23ihao// 循环结束了
}