template<typename T>
void Swap(T &a ,T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
在使用模板函數時,編譯器根據實際的型別生成相應的函數定義。
並非所有的型別都使用相同的演演算法,可以像過載常規函數那樣過載模板函數定義。
template<typename T>
void Swap(T &a ,T &b); //#1
template<typename T>
void Swap(T *a ,T *b,int n);//#2 最後一個引數是具體型別
int main()
{
int i =10,j=20;
Swap(i,j);//使用#1
const int Lim = 8;
int d1[Lim]={0,1,2,3,4,5,6,7};
int d2[Lim]={7,6,5,4,3,2,1,0};
Swap(d1,d2,Lim);//使用#2
}
template<typename T>
void Swap(T &a ,T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
template<typename T>
void Swap(T *a ,T *b,int n)
{
T temp;
for(int i=0;i<n;i++)
{
temp =a[i];
a[i]=b[i];
b[i]=temp;
}
}
某些時候,型別T的相應操作只適用於陣列,如果T為結構體則模板函數便不成立
同樣,如if(a>b)
,如果T為結構,則>便不成立
解決方案:
當編譯器找到與函數呼叫匹配的具體化定義時,將使用該定義,不再尋找模板。
template<>
開頭,並通過名稱來指出型別void Swap(job& ,job&);
template <typename T>
void Swap(T&,T&);
template<> void Swap<job>(job& ,job&);//顯示具體化
//Swap<job>中<job>是可選的,因為函數的引數型別表明,這是job的一個具體化,所以也可以這樣寫:
template<> void Swap(job& ,job&);
注意:函數模板並不會生成函數定義,他只是生成一個用於生成函數定義的方案,編譯器使用模板為特定的型別生成函數定義時,得到的是模板範例。
template<typename T>
void Swap(T &a ,T &b);
int a =10,b=20;
Swap(a,b);//因為提供了int型別的引數,所以自動生成了int型別的模板範例。這樣是==隱式範例化==
//也可以直接命令編譯器建立特定的範例
//顯示範例化
template void Swap<int>(int &,int &);//使用Swap()模板生成int型別的函數定義
//顯示具體化
template<> void Swap<int>(int& ,int&);
template<> void Swap(int& ,int&);
//區別在於:具體化是不使用Swap()模板函數生成函數定義,而是使用專門為int型別顯示定義的函數定義
//簡單的理解,具體化是對函數的宣告,而範例化是對模板函數的使用
template<typename T>
T Add(T a,T b)
{
return a+b;
}
int m=6;
double x=10.5;
Add<double>(x,m); //與Add(x,m)不匹配,因為一個是int一個是double
//通過Add<double>範例化,可強制將m轉為double
//但是同樣的對Swap便不能成功,因為Swap中使用的是參照型別
Swap<double>(m,x);//double& 不能指向int
//使用案例
template <typename T>
void Swap(T &,T &);
template<> void Swap<job>(job&,job&);//具體化
int mian()
{
template void Swap<char>(char& ,char&);
short a,b;
Swap(a,b);//隱式範例化
job n,m;
Swap(n,m);//顯示具體化
char g,h;
Swap(g,h);//顯示範例化
}
template<class T1,class T2>
void fun(T1 x,T2 y)
{
?type? s=x+y; //因為是模板函數,此時?type?型別不確定
}
C++11增加decltype
關鍵字
template<class T1,class T2>
void fun(T1 x,T2 y)
{
decltype(x+y) s=x+y; //s型別與x+y的型別一致
}
使用decltype(expression) var
的步驟:
double x =5.5;
double& z =x;
const double* pd;
decltype(x) w; //w為double型別
decltype(z) u; //u為double& 型別
decltype(pd) v; //v為const double* 型別
double x = 4.5;
decltype((x)) r = x;//r是double&型別
decltype(x) r = x;//r是double型別
//括號不會改變expression的值和左值性
//可理解為加括號僅僅是decltype宣告參照的一種方式
int j=3;
int &k=j;
int &n=j;
decltype(j+6) x; //x是int
decltype(k+n) y;//y是int ,雖然k和n是參照,但是k+n不是參照是2個int的和
如果多次宣告,可以結合typedef
和decltype
typedef decltype(x+y) xytype;
xytype z = x+y;
xytype arr[10];
但是某些需定義返回值型別的函數模板任然不能得到解決,如:
template<class T1,class T2>
?type? fun(T1 x,T2 y) //此時無法確定型別
{
return x+y;
}
C++新增語法auto h(int x,float y) -> double
,這稱為後置返回型別,auto是一個預留位置
template<class T1,class T2>
auto fun(T1 x,T2 y)->decltype(x+y) //後置型別使用decltype
{
return x+y;
}