函数模板
Posted lsongzhi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数模板相关的知识,希望对你有一定的参考价值。
函数模板
函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型替换.通过将类型作为参数传递给模板,可使编译器生成该类型的函数,由于模板允许以泛型的方式编写程序,因此有时也被称为通用编程,由于类型是用参数表示的,因此模板特性有时也被称为参数化类型(parameterized types).
==使用==
// 模板声明
template <typename AnyType>
void Swap(AnyType &a, AnyType &b);
// 模板定义
template <typename AnyType> // typename可以用关键字class代替,类型名可以任意选择
void Swap(AnyType &a, AnyType &b) {
AnyType temp;
temp = a;
a = b;
b = temp;
}
模板并不创建任何函数,只是告诉编译器如何定义函数.函数模板不能缩短可执行程序,最终的代码不包含任何模板,而只包含了为程序生成的实际函数.使用模板的好处是,它使生成多个函数定义更简单,更可靠.更常见的是将模板放在头文件中,并在需要使用模板的文件中包含头文件.
重载模板
可以向重载常规函数定义那样重载模板定义,和常规重载一样,被重载的模板的函数特征标必须不同.
template <typename T>
void Swap(T &a, T &b);
template <typename T>
void Swap(T *a, T* b, int n);
显式具体化
可以提供一个具体化函数定义--称为显式具体化(explicit specialization),其中包含所需的代码.当编译器找到与函数调用匹配的具体化定义时,将使用该定义而不再寻找模板.
- 对于给定的函数名,可以有非模板函数,模板函数和显示具体化模板函数以及它们的重载版本
- 显式具体化的原型和定义应以
template<>
打头,并通过名称来指出类型 - 具体化优先于常规模板,而非模板函数优先于具体化和常规模板
// 非模板函数
void Swap(job &, job &);
// 模板
template <typename T>
void Swap(T &a, T &b);
// 显式具体化
template <> void Swap<job>(job &, job &); // Swap<job> 中的<job>是可选的
实例化和具体化
编译器使用模板为特定类型生成函数定义时,得到的是模板实例(instantiation),这种实例化方式称为隐式实例化.
C++还允许==显式实例化==(explicit instantiation)
template void Swap<int>(int, int);
// 还可以在程序中使用函数来创建显式实例化
template <typename T>
T Add(T a, T b) {
return a + b;
}
int m = 6;
double x = 10.2;
cout << Add<double>(x, m) << endl;
隐式实例化,显式实例化和显式具体化统称为具体化(specialization).它们的相同之处在于,它们表示的都是使用具体类型的函数定义,而不是通用描述.不同之处在于,实例化使用的是和通用描述一样的模板,而显式具体化则需要额外的函数定义.
重载解析
过程
- 创建候选函数列表.其中包含于被调用函数的名称相同的函数和模板函数
- 使用候选函数列表创建可行函数列表,这些都是参数数目正确的函数,为此有一个隐式转换序列,其中包含实参类型与相应的形参类型完全匹配的情况.
- 确定是否有最佳的可行函数,如果有,则使用它,否则该函数调用出错.
关键字decltype
使用:
decltype(expression) var;
如果expression是一个没有用括号括起的标识符,则var的类型与该标识符的类型相同,包括const等限定符
如果expression是一个函数调用,则var的类型与函数的返回类型相同(并不会实际调用该函数)
如果expression是一个左值,则var为指向其类型的引用.但是要进入第三步,expression不能是未用括号括起的标识符(否则就会进入第一步),一种情况是,expression是用括号括起的标识符.
double xx = 4.4; decltype((xx)) r2 = xx; // r2 is double & decltype(xx) w = xx; // w is double
括号并不会改变表达式的值和左值性
如果前面的条件都不满足,则var的类型与expression的类型相同
另一种函数声明语法(C++11后置返回类型)
template <typename T1, typename T2>
auto h(T1 x, T2 y) -> decltype(x + y) {
return x + y;
}
以上是关于函数模板的主要内容,如果未能解决你的问题,请参考以下文章