(一)模板定义
假设想要编写一个函数比较两个值的大小关系。当我们想要比较几组不同的值的时候,我们可以通过函数的重载来实现,这样不免有点麻烦,因为数据类型还是比较多的,因此我们可以采用模板。我们可以不用为每个类型定义一个新函数,知识定义一个函数模板。函数模板是独立于类型的函数,可作为一种方式,产生函数特定的类型版本。
//重载形式
int compare(int& v1,int &v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
return 0;
}
int compare(string& v1,string &v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
return 0;
}
//模板形式(注意模板形参表不能为空)
template<typename T>
int compare(const T& v1,const T& v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
return 0;
}
模板形参表很像函数形参表,函数形参表定义了特定类型的局部变量但并不初始化那些变量,在运行的时候再提供实参来初始化形参
同样,模板形参表示可以在类或函数的定义中使用类型或值。例如compare函数声明一个名为T的类型形参。在compare内部,可以使用名字T引用一个类型,T表示那个实际类型由编译器根据所用的函数而确定。
模板新参可以使表示类型的类型形参,也可以是表示常量表达式的非类型形参。
使用函数模板
使用函数模板时,编译器会推断那个模板实参绑定到模板形参,一旦编译器确定了实际的模板实参,就称它实例化了函数模板的一个实例。
inline函数模板
函数模板可以用与非模板函数一样的方式声明为inline.不过说明符得放在模板形参表之后,返回类型之前。不能放在关键字template之前。
//ok
template<typename T>inline T min(const T&,const T&);
//error
inline template<typename T>T min(const T&,const T&);
定义类模板和定义函数模板类似,如下定义一个类模板
//定义一个类模板
template<class Type>
class Queue
{
public:
Queue();
Type &front();
const Type &front()const;
void push(const Type &);
void pop();
bool empty() const;
};
与调用函数模板形成对比,使用类模板时,必须为模板形参显式指定实参
(三)模板形参作用域
模板形参的名字可以在声明为模板形参后知道模板声明或定义的末尾使用。
模板形参遵循常规名字屏蔽规则。与全局作用域中声明的对象、函数或类型同名的模板形参会屏蔽全局名字
使用模板形参的名字不能在内部重用,这还意味着模板形参的名字只能在同一模板形参表中使用一次。
如同重用函数形参名字一样,模板形参的名字也能在不同模板中重用。
(四)模板声明
像其他任意函数或类一样,对于模板可以只声明而不定义。声明必须指出函数或类是一个模板,并且对同一个模板来说,在声明和定义时候模板形参名字不一定要一样。
并且每个非类型形参前面必须加上类型名字,省略关键字或者类型说明符是错误的。
template<class U> U calc(const U&,const U&);
template<class Type>
Type calc(const Type&,const Type&){}
(五)模板类型形参
类型形参由关键字class或typename后接说明符构成。在模板形参表中两个具有相同的含义,都指出后面所接的名字表示一个类型。
(六)非类型模板形参
模板新参不必都是类型,还可以是非类型形参。
(持续更新中)