8.5

8.5 函数模板

函数模板是通用的函数描述, 使用泛型来定义函数
其中的泛型可以用具体的类型替换, 通过类型作为函数参数传递给模板, 使编译器生成该类型的函数
C++函数模板功能能自动完成类型的替换过程:将所有int转换为double, 不会出现错误
允许以任意类型定义参数
template // AnyType可以任意选择, 遵守命名规则, 只对下一行的函数有效, 定义和声明前都要加上
void Swap(AnyType &a, AnyType &b)
{
AnyType temp;
temp = a;
a = b;
b = a;
}
template // C++98添加typename之前, 使用class
最终的代码不包含任何模板, 使用不同的参数, 就会出现不同的独立的函数定义

重载模板

和常规函数定义一样重载模板定义
重载
(T &, T &)
(T [], T [], int)

模板的局限性

对一些类型使用没有定义的运算符, 可能会出错。
重载运算符第11章
为特定的类型提供具体化的模板定义

显示具体化

struct job
{
char name[40];
double salary;
int floor;
};

第三代具体化

给定的函数名:非模板函数、模板函数、显式具体化模板函数和他们的重载版本。
显式具体化的原型和定义应以template<>打头, 并通过名称来指定类型
具体化优于常规模板, 非模板函数优于具体化和常规模板
void Swap(job &, job &); // 非模板函数
template // 模板函数
void Swap(T &, T &);
template<> void Swap(job &, job &); // 具体化, 可以省略, 相当于用模板函数指定了具体类型

实例化和具体化

函数模板本身不会生成函数定义

隐式实例化

只有在调用时, 指定了具体参数, 编译器才会生成一个模板实例。

显示实例化

template void Swap(int , int); // 使编译器生成一个使用int类型的实例。使用Swap模板生成一个int类型的函数定义

显示具体化

template<> void Swap(int &, int &);
template<> void Swap(int &, int &);
不要使用Swap模板生成函数定义, 应使用专门为int类型显示地定义的函数定义
当同一文件中使用显示实例化和显示具体化将会出错
int x = 10;
double m = 1.0;
Add(x, m); // 为类型double生成显示实例化。
统称为具体化
表示的都是使用具体类型的函数定义, 而不是通用描述。

编译器选择使用哪个函数版本