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)\)被稱為后置返回類型


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM