写在前面
在c++11中新引入了Variadic Templates(可变参数列表),和initialize_list不同的是,Variadic Templates可以支持不同类型的参数,而initialize_list只支持同一种类型的参数,并且在vector、max等容器或者函数中内部已经实现了initialize_list,那么Variadic Templates的用法更加广泛,其中体现最好的就是Tuple容器
Variadic Templates用法
使用Variadic Templates中重点为… ,他就是所谓的一个包,表示0~任意个数、任意类型的参数,一个应用的实例:
sample 1.简单样例
void printX(){ cout << "the last one!"<<endl;} //0个的时候调用此函数
template<typename T,typename... Types> //模板参数包
void printX(const T& firstArg,const Types&... args) //函数参数包 每次在args中分离出一个firstArg出来 最终调用printX()函数
{
cout << sizeof...(args)<<" "; //得到参数列表的长度
cout << firstArg << endl;
printX(args...); //传递args...
}
int main()
{
printX(7.5,"hello",'c',42);
return 0;
}
//输出
//7.5
//"hello"
//'c'
//42
Variadic Templates基本用法如上所述,我们拆分Variadic Templates使用递归的方式,每次在args中拆分出一个参数作为firstArg,可以使用sizeof…(args)来查看参数包剩余参数的个数,最终如果参数包args…为空,会调用没有参数的printX重载函数,最终结束递归调用
sample 2.max函数的Variadic Templates版本
在标准库中max函数有initialize_list类型的重载类型,但是没有Variadic Templates的重载类型
int maximum(int n)
{
return n;
}
template<typename...Args>
int maximum(int n,Args...args)
{
return max(n,maximum(args...));
}
int main()
{
cout << maximum(1,2,2,4,5,1);
return 0;
}
但是如果参数类型个数不确定,但是参数类型相同,使用initialize_list更方便快捷,但是需要在参数外面需要增加{}进行修饰,使用Variadic Templates要进行递归,效率会有所差别
sample 3.模拟tuple输出实现
c++11中新引入的容器tuple,tuple可以接受任意类型任意个数的参数,他的输出,在原函数库中已经重载实现
#include <iostream>
#include <tuple>
using namespace std;
int main()
{
tuple<int,float,char,string> f = make_tuple(42,2.1,'x',"hello");
cout << f << endl;
}
//输出
//[42,2.1,'x',"hello"]
下面模拟实现一下(程序没有进行测试):
template<int IDX,int MAX,typename...Args>
struct PRINT_TUPLE{
static void print(ostream& os,const tuple<Args...>& t){
os<<get<IDX>(t)<<(IDX+1==MAX?"":",");
PRINT_TUPLE<IDX+1,MAX,Args...>::print(os,t); //递归调用
}
};
template <int MAX,typename... Args>
struct PRINT_TUPLE<MAX,MAX,Args...>{
static void print(ostream& os,const tuple<Args...>& t){
}
};
template<typename...Args>
ostream& operator<<(ostream& os,const tuple<Args...>& t)
{
os<<"[";
PRINT_TUPLE<0,sizeof...(Args),Args...>::print(os,t);
return os<<"]";
}
sample 4.模拟tuple内部实现
容器tuple内部实现模拟
#include <iostream>
#include <initializer_list>
#include <algorithm>
#include <thread>
#include <cmath>
#include <vector>
#include <tuple>
#include <utility>
#include <type_traits>
#include <new>
#include <complex>
#include <tuple>
#include <map>
using namespace std;
template<typename... Values> class _tuple; //这里表示_tuple是一个模板类,并且 模板参数可以是0~无穷个。 所以下面的多个参数和0个参数才正确编译
template<> class _tuple<>{
public:
_tuple(){}
};
template<typename Head,typename... Tail> //不希望产生实参个数为0的变长参数模板
class _tuple<Head,Tail...>:private _tuple<Tail...> //继承自参数少一个的tuple
{
typedef _tuple<Tail...> inherited;
protected:
Head m_head;
public:
_tuple() = default;
_tuple(Head v,Tail... vtail)
:m_head(v),inherited(vtail...){}
auto head() -> decltype(m_head) { return m_head;} //使用decltype进行类型推导
// Head head(){ return m_head; }
inherited& tail(){ return *this; } //return后转换为inherited
};
int main()
{
_tuple<int,float,string> t(41,6.3,"nico");
cout << sizeof(t) << endl;
cout << t.head() <<endl;
cout << t.tail().head() <<endl;
cout << t.tail().tail().head() <<endl;
return 0;
}
上面使用继承的方式进行模拟,我们也可以使用类中套类对象的方式进行模拟实现:
#include <iostream>
#include <initializer_list>
#include <algorithm>
#include <thread>
#include <cmath>
#include <vector>
#include <tuple>
#include <utility>
#include <type_traits>
#include <new>
#include <complex>
#include <tuple>
#include <map>
using namespace std;
template<typename... Values>class tup;
template<>class tup<>{};
template<typename Head,typename... Tail>
class tup<Head,Tail...> //特化版本
{
typedef tup<Tail...> composited;
protected:
composited m_tail;
Head m_head;
public:
tup(){}
tup(Head v,Tail... vtail)
:m_tail(vtail...),m_head(v){}
Head head(){ return m_head; }
composited& tail(){ return m_tail; }
};
int main()
{
tup<int,float,string> t(41,6.3,"nico");
cout << sizeof(t) <<endl;
cout << t.head() <<endl;
cout << t.tail().head() <<endl;
cout << t.tail().tail().head() <<endl;
return 0;
}
在tup类中包含一个tup对象,在构造对象时,会依次向下调用构造函数,直到调用到没有参数的特化版本的tup的构造函数,对象构造完毕
推荐相关文章元组tuple:https://editor.csdn.net/md?articleId=118230056
参考资料
程序全部源自于《c++标准11-14》 侯捷
原文链接:https://blog.csdn.net/li1615882553/article/details/87454693
如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810