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