标签:文件中 允许 特定 过程 编译 函数名 重载 重载解析 引用
函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型替换.通过将类型作为参数传递给模板,可使编译器生成该类型的函数,由于模板允许以泛型的方式编写程序,因此有时也被称为通用编程,由于类型是用参数表示的,因此模板特性有时也被称为参数化类型(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的类型相同
template <typename T1, typename T2>
auto h(T1 x, T2 y) -> decltype(x + y) {
return x + y;
}
标签:文件中 允许 特定 过程 编译 函数名 重载 重载解析 引用
原文地址:https://www.cnblogs.com/lsongzhi/p/9557529.html