核心简记
模板是创建类或函数的公式,为编译时使用。
模板应该尽力减少对实参类型的要求。
使用模板时才会生成代码,定义模板并不会。因此为了编译模块找到定义,必须把模板类/函数定义、声明等都放在头文件供使用。
c++为了一遍编译语法大量多余.比如区分T的静态对象与类型对象、返回值在作用域外之类,都是为了编译时可以一遍编译而设置的。
定义模板
函数模板
|
|
模板定义使用关键字template开始,<>内为模板参数列表,不能为空。使用模板时隐式或显示将模板实参绑定模板参数上。
对于函数可以自动推断,或显示使用:
类型参数在函数体内任意使用。声明为类型时class或typename都可以当关键字。类型还可以是一个值:
实例化时必须传入常量表达式,值的类型可以是整形、指针、左值引用。
类模板
编译器不能为类模板自动推断类型,必须手动使用<>
定义方式:
每个实例生成独立的类,与其它同一模板生成的无关。
定义在类模板内的函数隐式inline,外的定义方式:
在A
一个类模板的成员函数只有使用时才实例化,这使得传入类型不必完全符合模板操作要求。
杂记
友元与模板各自是否是模板是无关的。
根据声明方式可以模板类型一对一、一对多、多对一。
可以使用typedef A< int> AINT 简化一个实例,using则可更改模板名。
static成员绑定实例,使用时实例化.
T可以是任意名字,名字在编译时都作为符号表项,因此不同类型的名字作用域是互相影响的,模板参的名字也按名字查找与隐藏。
模板也可以声明
使用T的类型成员时前要加typename。否则会当成静态成员。
可以加默认模板实参:template < typename T=int> 使用时即使使用默认也要加<>
成员模板不能是虚函数,可以与类模板独立定义,独立处理类型。
可以使用显示实例化提前实例一个模板实例:
定义时实例化到模块、声明连接用。
模板的参数推断能转化的只有顶层、底层const、函数数组指针。
指定类型时可按一般的转化。
type_traits库中有类型转化的模板,如将引用、const去掉等。
多个模板函数与普通函数可选时:
选同好->选非模板->选作用范围更小的模板(更特例化)
可以使用…传多个模板参数与模板函数的参数。
模板可以特例化,即手动代替编译器的部分工作,函数模板特例化生成函数的实例。
类模板的特例化甚至可以只是部分特例化,生成范围更小的模板。如hash< type>的定义使用、之前type_traits库的转化。
反编译
为编译时任务,在反汇编时基本看不出差别。都是普通的对象生成与函数调用。