c++中,模板是泛型编程的基础.模板是创建类或函数的蓝图或公式。
函数模板是一个独立于类型的函数,可作为一种方式,产生函数的特定类型版本。
模板定义以关键字template开始,后接模板形参表,模板形参表是用尖括号括住的1个或多个模板形参的列表,形参之间以逗号分隔.
#include "stdafx.h"
#include <iostream>
#include<string>
using namespace std;
template <typename T>
int compare(const T &v1,const T &v2)
{
if(v1<v2) return -1;
if(v2<v1) return 1;
return 0 ;
}
int _tmain(int argc, _TCHAR* argv[])
{
cout<<compare(1,2)<<endl;//用int代替T
cout<<compare(1.1,2.2)<<endl;//用float代替T
cout<<compare(string("good"),string("youcan"))<<endl;//用string代替T
return 0;
}
输出结果: -1 -1 -1
模板形参表定义了特定类型的局部变量但并不初始化那些变量,在运行时再提供实参来初始化形参。
例如:compare函数声明了一个名为T的类型形参。在compare内部,可以使用名字T引用一个类型,T表示哪个实际类型由编译器根据所用的函数确定。
模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参。非类型形参跟在类型说明符之后声明。类型形参跟在关键字class或typename之后定义,例如,class T是名为T的类型形参,在这里class和typename没有区别
使用函数模板时,编译器会推断哪个(或哪些)模板实参绑定到模板形参.一旦编译器确定用什么类型代替每个类型形参,就称它实例化了函数模板的一个实例.
inline函数模板
函数模板可以用与非模板函数一样的方式声明为inline.说明符放在模板形参表之后、返回类型之前,不能放在关键字template之前。
template<typename T> inline T min(const T&,const T&);
模板类型形参
类型形参由关键字class或typename后接说明符构成。在模板形参表中,这两个关键字具有相同的含义,都指出后面所接的名字表示一个类型。
模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型说明符或类类型说明符的使用方式完全相同。具体而言,它可用于返回类型或函数形参类型,以及在函数体重用于变量声明或强制类型转换。
非类型模板形参
在调用函数时非类型形参将用值代替,值的类型在模板形参表中指定.模板飞类型形参是模板定义内部的常量值,在需要常量表达式的时候,可使用非类型形参指定数组的长度。
例如:
template<class T,size_t N> void array_init(T (&parm)[N])
{
for(size_t i = 0;i!=N;++i)
{
parm[i]=0;
}
}
在函数模板内部完成的操作(如比较大小)限制了可用于实例化该函数的类型。程序员的责任是保证用作函数实参的类型实际上支持所用的任意操作,以及保证在模板使用那些操作的环境中那些操作运行正常。
注意:在编写模板代码时,对实参类型的要求尽可能少是很有益的.
编写泛型代码的两个重要原则:
1.模板的形参是const引用
2.函数体重的测试只用<比较。
形参设置为const的引用,就可以允许使用不允许复制的类型。大多数类型都允许复制(除IO类型之外).但是也有不允许复制的类类型.将形参设为const引用,保证这种类型可以用于compare函数,而且,如果有比较大的对象调用compare,则这个设计还可以使函数运行的更快。
模板是一个蓝图,他本身不是类或者函数。编译器用模板产生指定的类或函数的特定类型版本。产生模板的特定类型实例的过程叫做实例化。
模板实参推断
从函数实参确定模板实参的类型和值的过程叫做模板实参推断。
1.多个类型形参的实参必须完全匹配。
注意.当形参为引用时,数组是不能转换为指针的.
非类型形参的模板实参
实参必须是编译时常量表达式.