函数模板可以用来创建一个通用功能的函数, 以支持多种不同形参,简化重载函数的设计。
函数模板定义如下:
template<模板参数表>
返回类型函数名(形式参数表)
{
.....;//函数体
}
<模板参数表> (template parameter list)尖括号中不能为空,参数可以有多个,用逗号分开。模板参数主要是模板类型参数。
模板类型参数(template type parameter)代表-种类型,由关键字class 或typename (建议用typename)后加一个标识符构成,在这里两个关键字的
意义相同,它们表示后面的参数名代表一个潜在的内置或用户设计的类型。多用T表示
例子:
templateTmy_max(Ta,Tb) { return a > b? a:b; } int main() { my_max(12,23); my_max('a','b'); my_max(12.23,34.45); return 0; }
templatevoid PrintAr(T(&ar)[N]) { cout << typeid(T).name() << endl; for (int i = 0; i < N; ++i) { cout << ar[i] << "" << endl; } } int main() { int ar[] ={ 1,2,3,4,5,6,7 }; double dr[] = { 1.2,2.3,3.4, 4.5,5.6,6.7 }; char str[] = { "yhping"}; PrintAr(ar); PrintAr(dr); PrintAr(str); }
模板有完全泛化,部分特化,完全特化之分
template函数模板void fun(Ta)//完全泛化 //任何类型 { T x,y; cout << "T type:" << typeid(T). name() << endl ; cout <<" a type: "<< typeid(a). name() << endl; } template void fun(T* a) //部分特化版本 //只要指针类型 { T x,y; cout << "T type:" << typeid(T). name() << endl; cout <<" a type: "<< typeid(a). name() << endl; template<> void fun (char* a) //完全特化 只要char*类型 { T x,y; cout << "T type:" << typeid(T). name() << endl; cout <<" a type: "<< typeid(a). name() << endl; }
类型推导出T a 的类型
泛性
templatevoid fun(T a) { T x, y; cout << typeid(T).name << endl; cout << typeid(a).name << endl; } int main() { int x = 10; const int y = 20; int* xp = &x; const int* yp = &y; fun(x); //T int a int fun(y); //T const int a const int fun(&x); //T int * a int * fun(&y); //T const int * a const int * fun(xp); //T int * a int * fun(yp); //T const int * a const int * return 0; }
指针
templatevoid fun(T* a) { T x=0, y=0; cout << typeid(T).name << endl; cout << typeid(a).name << endl; } int main() { int x = 10; const int y = 20; int* xp = &x; const int* yp = &y; fun(&x); //T int a int * fun(&y); //T const int a const int * return 0; }
引用
template类模板void fun(T &a) { T x=0, y=0; cout << typeid(T).name << endl; cout << typeid(a).name << endl; } int main() { int x = 10; const int y = 20; int* xp = &x; const int* yp = &y; fun(x); //T int a int & fun(y); //T const int a const int & fun(xp); //T int * a int *&a 引用的指针 fun(yp); //T const int * a const int *&a return 0; } template void fun(T const &a) //系统无法推演出int *后面的const,只能推导前面的const 所以需要在int *后加const { T x=0, y=0; cout << typeid(T).name << endl; cout << typeid(a).name << endl; } int main() { int x = 10; const int y = 20; fun(x); //T int* a int * 等价于 int *const &p =&x fun(y); //T int const * a int const * 等价于 const int * const &q =&y; return 0; }
类模板里的函数都是模板函数,如果没有调用模板函数,就不会实例化该模板函数
模板参数有两种:模板类型参数和模板非类型参数
模板非类型参数template模板类型参数//N相当于宏 class Stack { T data[N]; public: void push(const T& x);//模板函数 }; int main() { Stack is; Stack ist; }
Array arr 是一个具体的类型,因为在编译后会替换成具体的int类型,就不是模板类型,模板类型是没有给出具体类型的
template总结:class Seq > //Seq模板类型必须前面有一个模板类型参数 class Container { Seq seq; public: void append (const T& t) { seq. push_back(t);} T* begin() { return seq.begin(); } T* end() { return seq.end(); } }; int main() { Container container; //Array是一个模板类型 Array 是一个具体的类型,要求参数是模板类型,所有不能实例化 return 0; }
函数模板根据一组实际类型或(和)值构造出独立的函数的过程通常是隐式发生的,称为模板实参推演(templateargument deduction)。
为了判断用作模板实参的实际类型,编译器需检查函数调用中提供的函数实参的类型。ia 的类型为int数组,dx的类型为double数组。都被用来
决定每个实例的模板参数。该过程称为模板实参推演。
在编译main函数中,由编译函数模板(functron template)而生成的函数,称为模板函数(template function)。这两个概念须分清楚。



