1. 模板定义
1.1 函数模板
函数模板是一个独立于类型的函数,可作为一种方式产生函数的特定版本。
模板定义以关键字template开始,后接模板形参表(不可为空)。
模板的形参可以分为:类型形参和非类型形参,编译器会为我们推测出用什么类型绑定类型形参以及用什么值绑定非类型形参
函数模板可以声明为inline,说明符放在形参表之后,返回类型之前,不可放在template之前
template <typename T> inline Tmin(const T&, const T&);
1.2 类模板
类模板同样以关键字template开头,后跟模板形参表。
使用类模板时,需要显示指定模板形参对应的实参,这点与函数模板不同。
template<class T> class Queue{
<span style="white-space:pre"> </span>T data;
}<pre name="code" class="cpp">Queue<int> qi;
1.3 模板形参
模板形参的名字没有意义,可以给模板形参赋予的唯一区别是区别形参是类型形参(表示未知类型)还是非类型形参(表示未知值)
模板形参作用域:模板形参之后到模板声明或定义的末尾处。
模板形参名字限制:不能再模板内部重用,这同时意味着模板形参的名字在统一模板中只能出现一次。
模板声明:模板可以只声明不定义,声明必须指出函数或类是一个模板,每个形参之前必须带上关键字,不可省略。
1.4 模板类型形参
typename和class关键字没有区别。
由于除定义数据成员或函数成员外,类还可以定义类型成员,因此模板函数中也可以使用这样的类型,但必须告诉编译器其为一个类型,因为编译器默认认定为数据成员。
template <class Parm,class U>
Parm func(Parm *array, U value){
<span style="white-space:pre"> </span>typenameParm::size_type *p;
}
通过在名字前加上typename作为前缀,可以告诉编译器将成员当做类型。这一声明给实例化func的类型增加了一个职责:哪些类型必须具有名为size_type的类型成员。
1.5 非类型模板实参
在调用函数时,非类型实参将用值代替。
template <class T, size_t N> void array_init(T(¶m)[N]){
for(size_t i = 0; i != N; ++i){
<span style="white-space:pre"> </span>parm[i]= 0;
<span style="white-space:pre"> </span>}
}
int x[42];
double y[10]
array_init(x);
array_init(y);
对于模板的非类型实参而言,求值结果相同的表达式将认为是等价的。
int x[42];
const int sz =40;
int y[sz+2];
array_init(x);
array_init(