c++11 Variadic Templates(...)(可变参数列表)

写在前面

在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值