函数模板是通用的函数描述,通过将类型作为参数传递给模板,使编译器生成可用具体的类型的函数。类似于:
template<class Any>
void swap(Any &a, Any &b);
对于不同类型使用同一种算法,可使用模板,有时需要像重载常规函数那样去重载函数模板。
void swap(Any &a, Any &b);
void swap(int &a, int &b);
假设:
struct job
{
char name[10];
int floor;
};
假设我们希望交换两个job结构的内容,直接互换job即可,但有时候我们只想交换name,不交换floor,但函数的参数列表是一样的,无法使用模板重载来提提供其他的代码,此时需要涉及到具体化函数的定义,即指定某个函数定义,不再匹配模板。
实例化和具体化
在代码中包模板本身不会生成函数定义,编译器会根据具体参数类型生成模板的具体实例,这种叫隐式实例化。如今C++允许显示实例化,意味着直接命令编辑器创建特定的实例,语法是在函数声明前加template:
template void swap<int>(int &, int &);
此外还可以显示具体化(一下二者等价)
template <> void swap<int>(int &, int &);
template <> void swap(int &a, int &b);
隐式实例化,显示实例化和具体实例化统称具体化,都表示使用具体的函数定义,而不是通用描述。再声明中使用前缀template和template<>来区分显示实例化和具体化。显示具体化必须有自己的定义,实例化不需要有自己的定义。
警告:试图在同一个编程单元中使用同一类型的显示实例和显示具体化将出错。
#具体化函数将覆盖常规函数,而非模板函数将覆盖具体化和常规模板!
编译器的选择
编译器通常会对参数进行所需要的转换,选择是从最佳到最差的顺序如下:
- 完全匹配,但常规函数优于模板。(两个完全匹配的模板,较具体的优先,显示具体化优于隐式)
- 提升转换(例如:char和shorts转int,floor自动转double)
- 标准转换(例如: int转char)
- 用户自定义转换
template <class Type> void f(Type T); //#1
template <class Type> void f(Type *T); //#2
struct blot {int a, char b[10];};
blot link = {25, "sport");
f(&link);
f(&link)与#1,#2都匹配,具体参照完全匹配,但是#2更具体,#1还需要将转换为指针,因为参数不需要再转换已经具体化为指针了。
网友评论