一个函数模板就是一个公式,可以用来生成针对特定类型的函数版本。
typename或者class,含义相同,可以互相使用,一个模板参数列表中也可以同时使用这两个关键字。
template <typename T>
int compare(const T &v1,const T &v2)
{
if(v1>v2) return -1;
if(v1<v2) return 1;
return 0;
}
cout<<compare(1,0)<<endl;// T为int;
vector<int>vec1{1,2,3},vec2{4,5,6};
cout<<compare(vex1,vec2)<<endl;// T为vector<int>;
在模板定义中,模板参数列表不能为空。
- 模板编译
当编译器遇到一个模板定义时,它并不生成代码。只有当我们实例化出模板的一个特定版本时,编译器才会生成代码。当我们使用(而不是定义)模板时,编译器才生成代码。
通常,当我们调用一个函数时,编译器只需要掌握函数的声明,类似的,当我们使用一个类类型 的对象时,类定义必须是可用的,但成员函数的定义不必出现。因此,将类定义和函数声明放在头文件中,而普通函数和类的成员函数的定义放在源文件中。
模板则不同:为了生成一个实例化版本,编译器需要掌握函数模板或者类模板成员的函数定义。因此,与非模板代码不同,模板的头文件通常既包括声明也包括定义。 - 大多数编译错误在实例化期间报告
#include <iostream> #include <string> #include <vector> #include <list> using namespace std; //fing算法模板,两个模板类型参数,一个表示函数的迭代器参数,一个表示值的类型; template <class iterator,class T> iterator Find(const iterator &beg,const iterator &end,const T&ele) { for(auto it=beg;it!=end;++it) { if(*it==ele) return it; } return end; } int main() { vector<int>ivec1={1,2,3,4,5,6,7,8,9,0}; auto ret=Find(begin(ivec1),end(ivec1),3); if(ret==end(ivec1)) cout<<"not find"<<endl; else cout<<"find"<<endl; list<string>str={"111","222","333"}; auto rett=Find(str.begin(),str.end(),"222"); if(rett==str.end()) cout<<"not"<<endl; else cout<<"find"<<endl; }
类模板
与函数模板不同之处,编译器不能为类模板推断模板参数类型,必须在模板名后的尖括号中提供额外信息来代替模板参数的模板实参列表。- 类模板的成员函数
既可以在类模板内部,也可以在类模板外部为其定义成员函数,定义在类模板内的成员函数被隐式声明为内联函数。
类模板的成员函数具有和模板相同的模板参数,定义在类模板之外的成员函数就必须以关键字template开始,后接类模板参数列表。