16.1.1 函数模板。
模板定义以关键字 template 开始。后接 模板形参表,模板形参表是用尖括号括住一个或多个形参列表,形参之间以逗号分隔。
模板形参可以是表示类型的 类型形参,也可以是 表示常量表达式 的非类型形参。
使用函数模板。
使用函数模板时,编译器会推断哪个或哪些模板实参 绑定到模板形参。
一旦编译器确定了对应的模板实参,就称为:实例化了一个函数模板实例。
inline 函数模板
template <typename T> inline T min(const T& ,const T&);
注意:inline 说明符放在模板形参之后,函数返回类型之前。
16.1.2 定义类模板。
可以像定义函数模板一样,定义类模板。
类模板的使用。
与函数模板由编译自动推导出实参类型不同。使用类模板时,必须为模板形参显式指定实参。
如:Queue< int > qi;
Queue < vector<double> > qc;
编译器使用模板实参来实例化这个类的。
16.1.3模板形参。
模板形参作用域:模板形参的名字,可以在声明为模板形参之后,直到模板声明或定义的末尾处使用。
template < typename T> // T 起效。
class demoClass
{
……
};//T 作用域范围。
模板形参遵循常规名字屏蔽规则。同名的,内层名字屏蔽外层。
与全局作用域中声明的 对象,函数,或类型,同名的模板形参会屏蔽它们的全局名字。
typedef double T; template <class T> T calc(const T &a, const T &b) //此处模板形参T屏蔽全局typedef { // tmp has the type of the template parameter T // not that of the global typedef T tmp = a; // ... return tmp; }
16.1.4,模板的 类型形参。
类型形参由关键字 class或typename 后接说明符构成。
这个类型形参,可以作为类型说明符,在模板的任何地方使用,就如同内置类型说明符(如,int,double)
在模板定义内部指定类型。
我们知道,类中可以定义 数据成员,函数成员,以及 类型成员。如STL中的size_type.
当我们要使用一个类型成员时,我们应当显式的指定这个名字是一个类型。
template <class Parm, class U> Parm fcn(Parm* array, U value) { Parm::size_type * p; // If Parm::size_type is a type, then a declaration // If Parm::size_type is an object, then multiplication } 以上用法,编译会以为是一个变量 size_type 与另一个p 相乘。
我们应当显式的告诉编译器,在这里,size_type是一个类型。
通过在类型成员前面加上关键字typename 作为前缀,可以显式告诉编译这个名字是一个类型。
如
template <class Parm, class U> Parm fcn(Parm* array, U value) { typename Parm::size_type * p; // ok: declares p to be a pointer }
在这里,typename Parm::size_type 就告诉编译,size_type是一个类型名,
typename Parm::size_type *p定义一个指向Parm::size_type类型的指针。
当然,前提是我们这里使用的类Parm有size_type这个类型成员。
16.1.5非类型模板形参。
模板形参不必者是类型。也可以是非类型。
1,函数模板.在调用函数时非类型形参将用值代替,值的类型在模板形参表中指定。
// initialize elements of an array to zero template <class T, size_t N> void array_init(T (&parm)[N]) { for (size_t i = 0; i != N; ++i) { parm[i] = 0; } }
N非类型形参。N的实参由编译器计算得到。
当调用 array_init时,编译器从数组实参计算非类型形参的值:
int x[42]; double y[10]; array_init(x); // instantiates array_init(int(&)[42] array_init(y); // instantiates array_init(double(&)[10]
模板非类型形参是模板定义内部的常量值。
当模板定义需要一个待定的常量值时,可以使用非类型形参。