C++函數模板淺析

	之前看《Effective C++》,作者將C++分成了四種次語言,分別是C,Object-Oriented C++,Template C++,STL;
今天就來簡單分析下模板編程部分;
	參考資料:《C++ primer Plus 第六版》和《Effective C++ 第三版》

一.爲什麼需要函數模板

先看幾個函數:

void swap(int& a,int& b)
{
int temp=a;
a=b;
b=temp;
}
void swap(double&a,double&a)
{
double temp=a;
a=b;
b=temp;
}



	除了變量的類型,函數的內容是一模一樣的,如果能有一種通用的模板,能夠讓程序自己根據類型填空完成函數不就能大大減
少工作量嗎?值得高興的是,C++中的模板功能能完成這一過程:


template<typename T>
void swap(T& a,T& b)
{
T temp=a;
a=b;
b=temp;
}


:注意到的是,在C++98之後才能使用關鍵字typename,之前都是使用class創建模板的;
調用的時候只需要像普通函數一樣調用函數模板就可以了:
int i=2,j=3;
swap(i,j);
這裏在編譯期間編譯器會自動進行參數類型的推演,然後爲對應的類型生成模板實例,即生成一個swap的int類型版本的代碼,這也是爲什麼
模板會使得代碼的體積膨脹,
----注:我目前尚不知道多次使用相同類型調用函數模板是否會導致創建多個模板實例,等進行實驗後回來補充這個問題-----

二.模板的重載

	實際上上面的模板定義是有缺陷的,因爲它假定了T類型是可以進行賦值運算的,而實際上有一些類型是不能進行賦值運算的,
對於這些類型,我們就需要定義不同的函數模板了。例如數組,數組是不能進行賦值操作的,所以需要爲各種類型的數組定義一個
模板:
	void swap(T a[],T b[],int n);//具體定義略

	這裏的模板的特徵標爲(T [],T[]);而原來的模板的特徵標爲(T&,T&);
重載就是同一個函數名而特徵標不同的一組函數,這裏也是滿足這個條件的,所以這就是函數模板的重載;
調用的時候依然是像普通函數那樣調用就可以了,編譯器照樣會生成對應版本的代碼;
三.顯式具體化
然而有些類型使用模板重載也無法做到通用模板,結構類型便是如此;

struct light
{
float R;
float G;
float B;
}
struct name
{
string firstName;
string lastName;
}


	這兩種結構類型是沒有辦法使用通用的模板的void swap(struct T&,struct T&);顯然沒法進行定義,這個時候就需要使用模板
的顯式具體化了-----提供一個具體的函數定義(話說這就是定義一個對應類型的函數出來):
--C++98標準使用瞭如下的具體化方法
--對於給定的函數名,可以有非模板函數、模板函數和顯示具體化模板函數以及它們的重載版本
--顯示具體化的原型和定義應以template<>打頭,並通過名稱來指出類型
--具體化優先於常規模板,而非模板函數優先於具體化和常規模板
例如:
//顯式具體化原型
template<> void swap<light>(light&,light&);
其中的<light>是可選的,因爲參數類型中以及說明了類型,即可修改爲 template<> void swap(light&,light&);

四.具體化和實例化

實例化:編譯器根據給出的模板生成對應類型的代碼
具體化:直接自己提供完整的函數定義,但是需要遵循上面提到的格式
請注意這兩者的微妙差別,實例化是編譯器提供代碼,而具體話則是程序員自己編寫代碼;
早期的編譯器只能通過隱式實例化,即程序員看不到編譯器生成的代碼,也不知道編譯器生成了代碼,也不能控制編譯器的代碼生成
,而現在C++還允許顯示實例化,這意味這可以直接命令編譯器創建特定的實例:
	其語法是,聲明所需的種類--用<>符號指示類型,並且在聲明前面 添加關鍵字template;
	template void swap<int>(int&,int&); //顯示實例化
	函數調用時 swap<int>(i,j);也是顯示實例化,但沒有中間的<>就是隱式實例化;
	當編譯器看到上面這條語句之後編譯器會爲swap()模板生成int類型的版本的代碼

	template<> void swap<int>(int&,int&);//顯示具體化
	template<> void swap(int&,int&);//顯示具體化
	編譯器看到這兩條語句後只是知道了代碼中有int 版本的代碼,並且不會爲它生成代碼


注意:在同一個文件中使用同一種類型的顯示實例和顯示具體化將出錯

	隱式實例化、顯示實例化和顯示具體化統稱爲具體話,它們的相同之處在於,它們表示的都是使用具體類型的函數定義,而不
是通用描述;

五.模板的特化和偏特化

這部分有許多作者都講的比較詳細完整,這裏就不多做解釋了,可以參考這一篇這一篇
函數的特化其實就是顯示具體化。
六.待續...



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章