函数模板是通用的函数描述,它们使用泛型来定义函数,其中的泛型可用具体的类型替换。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。由于模板允许以泛型(而不是具体类型)的方式编写程序,因此有时候也被称为通用编程。
在标准C++98添加关键字typename之前,C++使用关键字class来创建模板。例如:
在C++11中,可以将class替换为typename。
模板的显示具体化
假设有一个结构体,C++允许将一个结构体赋给另一个结构体,如果只想交换其中部分成员,则需要不同的代码。
可以提供一个具体化函数定义——显示具体化。当编译器找到与函数调用匹配的具体化时,将使用该定义,而不再寻找模板。
- 对于给定的函数名,可以有非模板函数,模板函数,和显示具体化函数以及它们的重载版本。
2.显示具体化的原型和定义应以template<>打头,并通过名称来指出类型。
3.具体化优先于常规模板,非模板函数优先于具体化和模板函数。
函数调用swap(i,j)导致编译器生成swap()的一个实例,该实例使用int类型。
模板并非函数定义,但使用int的模板实例就是函数定义,这种实例化方式被称为隐式实例化。
C++允许显示实例化,template void swap(int&, int & )
编译器选择使用哪个函数版本
对于函数重载,函数模板,函数模板重载,C++有定义一个良好的策略,来决定为函数调用使用哪一个函数定义,尤其是有多个参数时,这个过程称为重载解析。
1.完全匹配,但常规函数优先于模板。
2.提升转换(char 与short自动转换为int,float自动转换为double)。
3.标准转换(int转换为char,long转换为double)。
4.用户定义的转换,如类声明中定义的转换。
x + y 的类型无法预测出来,使用decltype关键字来猜测类型。
如果函数有返回值类型:无法预先知道x + y的类型,此时还未声明参数x 和 y,他们不在作用域内(编译器无法看到它们,无法使用它们)。必须在声明参数后使用decltype。
现在,decltype在参数后边声明,因此x, y位于作用域内,可以使用它们