1. 程式人生 > 其它 >C++函式模板即其例項化和具體化

C++函式模板即其例項化和具體化

也許更好的閱讀體驗

函式模板

C++函式模板實質上是一個生成函式的方式,它的目的是減少重複勞動。在呼叫函式模板時,編譯器會生成一個函式例項,這種方式被稱為隱式例項化。當我們對不同型別的變數執行同樣的操作時,如果用函式過載,會麻煩很多。
例如,我們打一個絕對值函式

int fabs (int a)
{
	return a>0?a:-a;
}

如果我們要對double型別也用絕對值函式,我們又得再打一個

double fabs (double a)
{
	return a>0?a:-a;
}

但如果用函式模板,那麼就只用打一次,不僅int,double都可以用,long ,float甚至自定義的型別也可以用。

template <class T>
T fabs (T a)
{
	return a>0?a:-a;
}
//定義兩個不同型別的模板這樣使用
template <class T1,class T2>

函式顯式例項化

即指示編譯器直接建立一個函式例項,上面說到,函式模板是一個生成函式的方式,顯式例項化就是告訴編譯器生成一個函式。
用法

template 函式型別 函式名 <模板型別>(模板型別);//尖括號可省略
eg:
template int fabs <int> (int a);
template int fabs (int a);

上述兩種寫法是一樣的

強制例項化

呼叫函式時可告訴編譯器使用哪種型別進行例項化,類似於變數的強制轉化。
用法舉例

fabs<long long>(a)

函式顯式具體化

當我們對不同型別要做不同處理方式時就用具體化。編譯器會對具體化的型別專門使用這個函式,類似於函式過載,不過這是對函式模板的特例化處理。
用法

template <> 函式型別 函式名 <模板型別>(模板型別)//尖括號可省略
{
	函式內容
}
eg:
template <> float fabs <float> (float a)
{
	return a+1;//隨便寫的內容
}

當我們呼叫函式時傳入的引數是兩個float時會使用上述函式
注意

不能對例項化和具體化一樣型別的函式模板,但可以另外定義相同型別相同名字的函式,即下面的程式碼不能同時存在

template <> int fabs (int a)
{
	return a+1;
}
template int fabs (int a);

但下面的程式碼可以

template int fabs (int a);//或者具體化
int fabs (int a)
{
	return a+2;//隨便寫的
}

呼叫函式時,在變數型別匹配的上時,優先使用非模板型別的,也可這樣操作告訴編譯器使用模板型別的函式

fabs<>(a);

關鍵字\(decltype\)

當我們使用了複數個模板時,如

template <class T1,class T2>
T1 f (T1 a,T1 b);

如果我們新定義一個變數\(c,c=a+b\)
那麼\(c\)的型別是什麼呢,舉個例子

f(1,5.5)//①
f(5.5,1)//②

如果c是T1型別,那麼①中本應該是6.5變成了6,如果是T2型別,那麼②中則變成了6
而關鍵字\(decltype\)就能很好的解決這種問題
我們這麼宣告c變數,

decltype(a+b) c=a+b;

這表示定義一個型別和a+b一樣的變數

後置返回型別

只有\(decltype\)是不夠用的,這無法滿足對函式返回值的定義
於是有了這麼個語法

auto f (T1 a,T1 b) -> decltype (a+b)

這將返回值型別的宣告後置了,\(->decltype(a+b)\)被稱為後置返回型別