template_12特化与重载

时间:2023-03-09 04:06:16
template_12特化与重载

1,重载函数模板
template_12特化与重载
f<int*>((int*)pi);//1
f<int>((int*)pi);//2
上面用int*替换第一个模板的T,用int来替换第二个模板的T。那么将得到两个相同参数类型(int*)的同名函数。
也就是不仅同名模板可以同时存在,它们各自具有相同参数类型和返回类型的实例化体也可以同时存在。

f(pi);对于这两个模板实参演绎都可以获得成功,即f<int*>(int*)和f<int>(int*).这也就意味着调用是二义性的。
但是,考虑重载解析的额外规则:选择"产生自更特殊的模板的函数"。因此选择了第二个模板。
当然如果要在两个特殊程度相同的模板中选择,将不能做出决定这是产生二义性。

模板函数也可以和非模板函数同事重载,会优先选择非模板函数。

2,签名
template_12特化与重载

template_12特化与重载

3,显式特化
类模板不能被重载,但可以使用另一种替换的机制来实现这种透明自定义模板功能,这就是显式特化,也称之为全局特化。
它为模板提供了一种使模板参数可以被全局替换的实现。
事实上类模版和函数模板都可以被全局替换,而且类模版的成员(成员函数,嵌入类,静态成员变量等)都能被全局替换。
全局特化和局部特化都没有引入一个全新的模板或模板实例,它们只是对原来的泛型(或非特化)模板中已经隐式声明的实例提供另一种定义。

template<> class S<特化的模板实参>

全局特化的实现并不需要与泛型实现有任何关联,可以包含不同名称的成员函数。全局特化只是和类模板的名称有关联。

4,全局类模板特化
template_12特化与重载

template_12特化与重载
对于特化的声明,因为它不是模板声明,所以应该使用(位于类外部)普通成员定义语法来定义全局类模板特化的成员,也就是不能指定template<>前缀。

template_12特化与重载
全局模板特化和由模板生成的实例化版本不能共存于同一个程序中。

template_12特化与重载
实例化置于全局模板特化位置之后,并且定义了全部模板特化,此时这个实例化其实是走的全局模板特化所以OK.

如果全局模板特化的编译单元与跟实例化或泛型声明的编译单元不在同一个编译单元,容易出现很难捕捉的错误。
我们需要确认特化的声明对泛型模板的所以用户都是可见的。
特化声明通常都应该位于模板声明之后。
然而泛型实现也可能来自外部资源包,我们可以创建一个包含泛型声明的头文件并让特化什么位于其后。
通常都应该避免让模板特化来自外部资源包。
template_12特化与重载

5,全局函数模板特化
全局函数模板特化和类模板特化大体上是一致的,唯一区别是:函数模板特化引入了重载和实参演绎这两个概念。

全局特化声明的声明对象并不是一个模板,因此对于非内联的全局函数模板特化的声明而言,在同个程序中它的定义只能很粗线一次。
全局函数模板特化的声明必须紧跟在模板定义的后面,以避免使用一个模板直接生成的函数。

特化声明禁止模板进行实例化;
为了避免出现重复定义错误,就不能把定义放在头文件里。解决方案是把这个特化声明为内联函数,此时该函数的定义就可以放在头文件中。

6,全局成员特化
template_12特化与重载

template_12特化与重载

7,局部类模板特化
template_12特化与重载

template_12特化与重载