C++函数模板 1 2 3 4 5 6 7 8 template <typename T>void Swap (T &a ,T &b) { T temp; temp = a; a = b; b = temp; }
在使用模板函数时,编译器根据实际的类型生成相应的函数定义。
重载的模板 并非所有的类型都使用相同的算法,可以像重载常规函数那样重载模板函数定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 template <typename T>void Swap (T &a ,T &b) ; template <typename T>void Swap (T *a ,T *b,int n) ;int main () { int i =10 ,j=20 ; Swap (i,j); 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); } 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<>
开头,并通过名称来指出类型 调用顺序是:非模板函数>具体化模板函数>模板函数 1 2 3 4 5 6 7 8 void Swap (job& ,job&) ;template <typename T>void Swap (T&,T&) ;template <> void Swap <job>(job& ,job&);template <> void Swap (job& ,job&) ;
实例化和具体化 注意: 函数模板并不会生成函数定义,他只是生成一个用于生成函数定义的方案,编译器使用模板为特定的类型生成函数定义时,得到的是模板实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 template <typename T>void Swap (T &a ,T &b) ;int a =10 ,b=20 ;Swap (a,b);template void Swap <int >(int &,int &);template <> void Swap <int >(int & ,int &);template <> void Swap (int & ,int &) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 template <typename T>T Add (T a,T b) { return a+b; } int m=6 ;double x=10.5 ;Add <double >(x,m); Swap <double >(m,x);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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); }
模板函数类型的确定 1 2 3 4 5 template <class T1,class T2>void fun (T1 x,T2 y) { ?type? s=x+y; }
C++11增加decltype
关键字
1 2 3 4 5 template <class T1,class T2>void fun (T1 x,T2 y) { decltype (x+y) s=x+y; }
使用decltype(expression) var
的步骤:
如果expression没有用括号括起来,则var与expression类型相同,包括const等限定符 1 2 3 4 5 6 double x =5.5 ;double & z =x;const double * pd;decltype (x) w; decltype (z) u; decltype (pd) v;
如果expression是一个函数调用,则var与返回值类型相同。并不会实际调用函数,编译器通过查看原型来确定返回值类型 如果expression是一个左值,则var为指向其类型的引用。常见的情况如下: 1 2 3 4 5 6 double x = 4.5 ;decltype ((x)) r = x;decltype (x) r = x;
如果前3条都不满足,则var与expression类型相同 1 2 3 4 5 6 int j=3 ;int &k=j;int &n=j;decltype (j+6 ) x; decltype (k+n) y;
如果多次声明,可以结合typedef
和decltype
1 2 3 typedef decltype (x+y) xytype ;xytype z = x+y; xytype arr[10 ];
但是某些需定义返回值类型的函数模板任然不能得到解决,如:
1 2 3 4 5 template <class T1 ,class T2 >?type? fun (T1 x,T2 y) { return x+y; }
C++新增语法auto h(int x,float y) -> double
,这称为后置返回类型,auto是一个占位符
1 2 3 4 5 template <class T1,class T2>auto fun (T1 x,T2 y) ->decltype (x+y) { return x+y; }