可變參模板

017可變參模板的例子

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>

using namespace std;

//可變參函數的簡單例子
/*
 * 1.我麼一般吧args稱爲一包或者一堆參數,而且這些參數類型是可以不同的。
 * 2.我們理解T這種類型,不要理解爲一個類型,而是0到多個類型。
 * 3.一包參數中可以容納0到多個模板參數,而且這些模板參數可以是任意類型。
 * 4.注意:
 *	T...   可變參類型,是一包類型
 *	args可變形參,一包形參
 *5.&的位置出現在類型名後面
 */
template<typename ... T>
void myFunction(T...args)
{
	cout << "args=" <<sizeof...(args) << endl;
	cout << sizeof...(T) << endl;
}


//例子2
template<typename T,typename ...U>
void myFunction02(const T&firstarg,const U&...otherargs)
{
	cout << sizeof...(otherargs) << endl;//sizeof...可變參的數量
}

void func()
{
	myFunction();
	myFunction(10, 20);
	myFunction(10, 20,23,4343.34);
	cout << "----------------------------------" << endl;

	myFunction02(1, 23, 43);//2,至少有一個參數
}

int main(void)
{
	func();
	system("pause");
	return 0;
}

/*
*(1)可變參函數模板 variadic templates
*允許模板中包含0個到任意個模板參數,在語法上和傳統的模板不一樣,使用  ...
*
*
*(3)
*
*
*/

018可變參函數模板參數包的展開_一個參數加一包函數容易解包

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>

using namespace std;

//遞歸終止函數
void myFunction02()
{
	cout << "參數解包完成,這是終止函數" << endl;
}


//例子2
template<typename T, typename ...U>
void myFunction02(const T&firstarg, const U&...otherargs)
{
	cout << sizeof...(otherargs) << endl;//sizeof...可變參的數量
	//注意下面的遞歸調用展開,,把一包東西分爲1+1包,直到最後爲1+0
	cout << "第一個參數的值爲:" << firstarg << endl;
	myFunction02(otherargs...);//當只有一個參數的時候,需要進行遞歸中值函數
	
}

void func()
{

	myFunction02(1, 23, 43);//2,至少有一個參數
}

int main(void){
	func();
	system("pause");
	return 0;
}

/*

*(2)可變參函數模板參數包的展開_一個參數加一包函數容易解包
*展開的套路比較固定,一般都是使用遞歸函數的方式來展開:c
*要求我們在代碼編寫過程中有一個參數包展開函數和遞歸終止條件。
* 一個參數+一包參數,最合適參數包的展開。
void myFunction02(const T&firstarg,const U&...otherargs)
*
*
*(3)
*
*
*/

019可變參類模板_通過繼承遞歸展開調用

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>

using namespace std;

//1.使用遞歸繼承方式展開參數包
template<typename ...Args>class myclass{};//主模板
//手寫一個參數爲0的特化版本
template<>class myclass<>//0個模板參數特化版本
{
public:
	myclass()
	{
		cout << "0個模板參數特化版本執行"<<this << endl;
	}
};

template<typename First,typename ...Other>
class myclass<First,Other...>:private myclass<Other...>
{
public:
	myclass():m_i(0)
	{
		cout << "myclass的構造函數執行了"<<this << endl;
	}
	//有參構造函數
	myclass(First parf,Other...Paro):m_i(parf),myclass<Other...>(Paro...)//調用父類的構造函數
	{
		cout << "有參數構造函數執行"<<this << endl;
	}
	
	
public:
	First m_i;
	
	
};

int main(void)
{
	myclass<int, float, double>myc;
	/*
	 * 執行三次構造函數
	 * myclass<int,float,double>--->myclass<int ,float>--->myclass<int>
	 *
	 * 	0個模板參數特化版本執行0020F73C
		myclass的構造函數執行了0020F73C
		myclass的構造函數執行了0020F73C
		myclass的構造函數執行了0020F73C
	 */
	cout << "----------------" << endl;
	myclass<int,float,double> my_class01(12, 123.565, 344.5845734958);
	/*
	 * 0個模板參數特化版本執行0039F74C
		有參數構造函數執行0039F74C
		有參數構造函數執行0039F74C
		有參數構造函數執行0039F74C
	 */

	system("pause");
	return 0;
}

/*
*(1)可變參類模板
*允許模板中定義0個到任意個模板參數,這是中高級話題,使用不多。
*	1.使用遞歸繼承方式展開參數包
	
每次子類都分成1+包,最後爲0,進行遞歸調用.

注意遞歸繼承
*	
*
*(2)在命令提示符裏面使用dumbin /all 文件名字 >mytext.txt
*查看有多少類生成。
*
*(3)2019年11月25日21:49:17
* Sunrise於東北電力大學第二教學樓1121實驗室

*
*
*/

020可變參類模板_通過遞歸組合方式展開函數包

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>

using namespace std;

//1.使用遞歸組合方式方式展開參數包
template<typename ...Args>class myclass {};//主模板
										   //手寫一個參數爲0的特化版本
template<>class myclass<>//0個模板參數特化版本
{
public:
	myclass()
	{
		cout << "0個模板參數特化版本執行" << this << endl;
	}
};

template<typename First, typename ...Other>
class myclass<First, Other...> //:private myclass<Other...>
{
public:
	myclass() :m_i(0)
	{
		cout << "myclass的構造函數執行了" << this << endl;
	}
	//有參構造函數
	myclass(First parf, Other...Paro) :m_i(parf),m_o(Paro...)//, myclass<Other...>(Paro...)//調用父類的構造函數
	{
		cout << "有參數構造函數執行" << this << endl;
	}


public:
	First m_i;
	//組合關係
	myclass<Other...>m_o;//參數多的類包含着參數少的類
};



int main(void)
{
	myclass<int, float, double> myclass01(1, 23.32, 34.545);
	/*
	 * 0個模板參數特化版本執行0041FA94
	有參數構造函數執行0041FA8C
	有參數構造函數執行0041FA84
	有參數構造函數執行0041FA7C

	組合關係對象首地址都不一樣
	 */
	
	system("pause");
	return 0;
}

/*
*(1)通過遞歸組合方式展開函數包
*
*(2)
*
*(3)
*
*
*/

021可變參類模板_通過tuple和遞歸調用展開函數包

#include<iostream>
#include<cstdlib>
#include<string>
#include<vector>
#include<queue>
#include<functional>

using namespace std;

//mycount用於統計,myMaxCount表示參數數量
template<int mycount,int myMaxCount,typename ...T>
class myclass
{
public:
	static void myFunction02(const tuple<T...>&t)
	{
		cout << "value="<<get<mycount>(t) << endl;
		myclass<mycount + 1, myMaxCount, T...>::myFunction02(t);
		
	}
};


//特化版本用於結束調用
template<int myMaxCount,typename ...T>
class myclass<myMaxCount,myMaxCount,T...>
{
public:
	static void  myFunction02(const tuple<T...>&t)
	{
		;
	}
};

template<typename ...T>
void myFunction(const tuple<T...>&t)//可變參函數模板
{
	myclass<0, sizeof...(T), T...>::myFunction02(t);
}


int main(void)
{
	//元組示意
	tuple<float, int, int>mytuple(12.34f, 100, 1);
	cout << get<0>(mytuple) << endl;
	cout << get<1>(mytuple) << endl;


	myFunction(mytuple);
	system("pause");
	return 0;
}

/*
*(1)通過tuple和遞歸調用展開函數包--需要些類的特化版本,有一定的難度。
*有一個從0開始的計數器,每次處理一個參數,計數器+1,一直到所有參數處理完畢。
*最後使用使用一個模板偏特化,作爲遞歸調用結束。
*
*(2)
12.34
100
value=12.34
value=100
value=1

*
*(3)總結
*	獲取參數包裏面的參數方式有很多種,但是一般來講都離不開遞歸這種手段。
*	
*
*
*/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章