码迷,mamicode.com
首页 > 其他好文 > 详细

函数模板

时间:2018-08-30 00:15:31      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:文件中   允许   特定   过程   编译   函数名   重载   重载解析   引用   

函数模板

函数模板是通用的函数描述,也就是说,它们使用泛型来定义函数,其中的泛型可用具体的类型替换.通过将类型作为参数传递给模板,可使编译器生成该类型的函数,由于模板允许以泛型的方式编写程序,因此有时也被称为通用编程,由于类型是用参数表示的,因此模板特性有时也被称为参数化类型(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).它们的相同之处在于,它们表示的都是使用具体类型的函数定义,而不是通用描述.不同之处在于,实例化使用的是和通用描述一样的模板,而显式具体化则需要额外的函数定义.

重载解析

过程

  1. 创建候选函数列表.其中包含于被调用函数的名称相同的函数和模板函数
  2. 使用候选函数列表创建可行函数列表,这些都是参数数目正确的函数,为此有一个隐式转换序列,其中包含实参类型与相应的形参类型完全匹配的情况.
  3. 确定是否有最佳的可行函数,如果有,则使用它,否则该函数调用出错.

关键字decltype

使用:

decltype(expression) var;
  1. 如果expression是一个没有用括号括起的标识符,则var的类型与该标识符的类型相同,包括const等限定符

  2. 如果expression是一个函数调用,则var的类型与函数的返回类型相同(并不会实际调用该函数)

  3. 如果expression是一个左值,则var为指向其类型的引用.但是要进入第三步,expression不能是未用括号括起的标识符(否则就会进入第一步),一种情况是,expression是用括号括起的标识符.

    double xx = 4.4;
    decltype((xx)) r2 = xx; // r2 is double &
    decltype(xx) w = xx; // w is double

    括号并不会改变表达式的值和左值性

  4. 如果前面的条件都不满足,则var的类型与expression的类型相同

另一种函数声明语法(C++11后置返回类型)

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!