1.声明模板的形式:
template <以逗号分隔的参数列>
其中的模板参数可以有一下几种形式:
1).类型参数。定义形式为:
class T或者typename T. 其中typename关键字为后期引入的关键字,T为类型参数。
eg: template<class T>
T max(T a,T b)
{
return a<b?b:a;
}
2).非类型模板参数。
函数模板和类模板的模板参数列表中可以包含其他的非类型模板参数,一些数值。并且可以给非类型模板参数设置默认值。
eg: template<typename T,int SIZE>
class stack{.....}
注:浮点类型和类类型,内部链接对象(如全局指针)类型不能作为非类型模板参数,。通常只能用整数类型,包括enum,或者使用指向外部链接值对象的指针来作为非模板参数。
一、函数模板
1.实例化
实例化方式一:自变量推导方式。eg:max(4,3);
注:(1)如果用一个类型实例化模板,但这个类型不支持模板中的操作,那么会出现编译错误。
(2)使用这种方式时,对相同的类型参数实例化,必须为同一个类型。实例化时,不支持自动类型转换,必须完全匹配。
eg:max(4,1.2);//这样的写法就错误,两个参数 类型必须完全相同。
(3)模板函数不支持自动类型转换。
实例化方式二:可以明确指定参数类型。max<double>(4,1.3);
注:如果函数返回值是模板参数,且不是调用参数中的任何一个,那么必须明确指定参数类型来实例化。可以只写不能推导出来的参数类型。
eg: template<typename R1,typename R2,typename R3>
R1 max(R2 const &a,R3 const &b)
...................
实例化必须明确指定参数类型,如:max<int,double,double>(4,4.2); //也可以写为:max<int>(4,4.2);
2.函数模板重载
非模板函数可以和同名的模板函数共同存在。
1).当非模板函数和同名的模板函数其他要素都相同时,优先选择非模板函数。
2).如果非模板函数和同名的模板函数其他要素相同,但非模板函数需要自动类型转换,则选用模板函数。
3).可以使用空的参数列表来避免调用非模板函数。方式如:max<>(4,3);
二、类模板
定义类模板的形式,和函数模板的声明形式相同。例如:
template <typename T>
class stack{
..........
上面的类的类型为:stack<T>。故使用类的类型时,都必须加上stack<T>。
在定义类的成员函数时,必须包含类模板头。
eg: template <typename T>
void stack<T>::push(T lem){......}
类成员的模板既可以是类模板,也可以自己定义的模板。
1.实例化
只有被调用到的成员函数才会被实例化。实例化时可以实例化为某些成员不支持的类型,但这些成员必须没有被调用。即:实例化的类型必须支持实际被调用到操作。
2.类模板的特化
方式:使用template<>开头声明此class,后面跟着特化结果。
eg: template<>
class stack<std::string>{.......};
1)偏特化
eg: template <typename T1,typename T2>
class MyClass{.....}
上面的模板可以有以下几个偏特化形式:
(1)template <typename T> //两个模板参数相同
class MyClass<T,T>{......}
(2)template<typename T> //一个模板参数为int
class MyClass<T,int>{.....}
(3)template<typename T1,typename T2> //两个模板参数为int
class MyClass<int ,int >
注:如果摸个声明和两个偏特化版本产生相同的匹配程度,则认为有歧义。
3.预设模板自变量
eg: template<typename T,typename COUT=std::vector<T>>
class stack{.....}
可以使用一个模板参数的那样调用这个类模板,这样第二个参数就为默认的模板参数了,并且可以引用前面定义的模板参数。
三、类型typename
用法一:用在模板参数列表中,用于定义模板。
用法二:用在模板内,用于表示某个标识符是类型。
eg: template <typename T>
class stack{
typename T::subtype:: *ptr;//表示subtype是class T类的一个类型。
......
}
四、.template构件
.template和->template用于template内,其后紧跟着与模板参数相关的物体。
只有当字符串字面值通过值传递时,才会被转型为一个指针;通过引用传递,则会被当成一个数组。
当在模板内,我们需要对内建类型默认初始化时,我们可以显示调用其构造函数。