C++函数模板的隐式实例化、显式实例化与显式具体化
来源:互联网 发布:免费网络电视 编辑:程序博客网 时间:2024/05/20 05:29
一、什么是实例化和具体化?
为进一步了解模板,必须理解术语实例化和具体化。
(1)、实例化:在程序中的函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例。这即是函数模板的实例化。
而函数模板实例化又分为两种类型:隐式实例化和显式实例化
例如:
template < typename T >void Swap( T &a, T &b ){ T temp; temp = a; a = b; b = temp;}
int main(void){ int a= 1, b = 2; Swap(a, b); Swap<int>(a, b); return 0;}
可以发现,在主函数中有两种Swap函数调用。
第一个Swap(a, b)导致编译器自动识别参数类型生成一个实例,该实例使用int类型,此为隐式实例化。
而第二个Swap<int>(a, b),直接命令编译器创建特定的int类型的函数实例,用<>符号指示类型,此为显式实例化。
(2)、具体化:即显式具体化,与实例化不同的是,它也是一个模板定义,但它是对特定类型的模板定义。显式具体化使用下面两个等价的声明之一:
template <> void Swap<int>(int &, int &);
template <> void Swap(int &, int &);
可以发现,显式具体化声明在关键字template后包含<>。上面声明的意思是"不要使用Swap()模板来生成函数定义,而应使用专门为int类型显式地定义的函数的定义"。这些原型必须有自己的函数定义。
在这里,有人可能要说了:”明明可以通过隐式实例化自动生成int类型的函数定义,为何还要弄出一个显式具体化来弄出另外一个模板呢?这不是多此一举吗?”
我要解释一下,显式具体化的主要用途!而在介绍用途之前,我们先来了解一下普通函数模板的局限性。
二、模板的局限性
假设有如下模板函数:
template <typename T>void fun(T a, T b){ ... }
通常,代码假定可执行哪些操作。例如,下面的代码假定定义了赋值。
a = b;
但是如果T为数组,这种假设将不成立!
同样,下面的语句假设定义了<
if ( a > b )
但如果T为结构,则该假设便不成立!
另外,为数组名定义了运算符 > ,但由于数组名是常量地址,因此它比较的是数组的地址,而这并不是我们所期望的操作。下面的语句假定为类型T定义了乘法运算符,但如果T为数组、指针或结构,这种假设便不成立:
T c = a * b;
总之,编写的模板函数很可能无法处理某些类型。通常在C++中有一种解决方案是:运算符重载,以便能将其用于特定的结构或类。就是说一个类重载了运算符+之后,使用运算符+的模板便可以处理重载了运算符+的结构。
但是,还有另外一种解决方案:为特定类型提供具体化的模板定义(这就是显式具体化的主要用途)。
三、显式具体化
假定定义了如下结构:
struct job{ char name[40]; double salary; int floor;}
另外,假设希望能够交换两个这种结构的内容。原来的模板使用下面的代码来完成交换:
temp = a;a = b;b = temp;
由于C++允许将一个结构赋给另一个结构,因此即使T是一个job结构,上述代码也可适用。然而,如果只想交换salary和floor成员,而不交换name成员,则需要使用不同的处理代码。但Swap() 的参数将保持不变(两个job结构的引用),因此无法使用模板的重载来提供其他代码(模板重载,模板的参数列表必须不同)。这时,就得用显式具体化来实现这个需求。
上面已经介绍过显式具体化的声明方式,我们直接通过代码实例来看一下:
#include <iostream>using namespace std;//job结构struct job{char name[40];double salary;int floor;};//普通交换模板template <typename T>void Swap(T &a, T &b){T temp;temp = a;a = b;b = temp;}//job类型的显式具体化模板template <> void Swap<job>(job &j1, job &j2){double t1;int t2;//交换salaryt1 = j1.salary;j1.salary = j2.salary;j2.salary = t1;//交换floort2 = j1.floor;j1.floor = j2.floor;j2.floor = t2;}int main(void){int inta = 1, intb = 2;job zhangSan = {"张三", 80000, 6};job liSi = {"李四", 60000, 4}; cout << "inta = " << inta << " inta = " << intb << endl;cout << zhangSan.name << " , " << zhangSan.salary << " , " << zhangSan.floor <<endl; cout << liSi.name << " , " << liSi.salary << " , " << liSi.floor <<endl; Swap(inta, intb); //编译器将实例化普通模板的int类型函数Swap(zhangSan, liSi); //编译器将实例化显式具体化模板job类型函数cout << "\n交换后:\n" << endl;cout << "inta = " << inta << " inta = " << intb << endl;cout << zhangSan.name << " , " << zhangSan.salary << " , " << zhangSan.floor <<endl; cout << liSi.name << " , " << liSi.salary << " , " << liSi.floor <<endl;return 0;}
运行截图:
在程序运行时匹配模板时,遵循的优先级是:
具体化模板优先于常规模板,而非模板函数优先于具体化和常规模板。
- C++函数模板的隐式实例化、显式实例化与显式具体化
- 函数模板之隐式实例化、显式实例化、显式具体化
- C++学习中的函数模版(显式具体化、隐式具体化、显式实例化)
- C++模板显式实例化,隐式实例化,特化(具体化,偏特化)辨析
- 模板显式、隐式实例化和(偏)特化、具体化的详细分析
- 模板显式、隐式实例化和(偏)特化、具体化的详细分析
- 模板显式、隐式实例化和(偏)特化、具体化的详细分析
- 模板显式、隐式实例化和(偏)特化、具体化的详细分析
- 模板显式、隐式实例化和(偏)特化、具体化的详细分析
- C++_模板的实例化与具体化。
- C++函数模板 模板实例化、具体化
- C++函数模板 模板实例化、具体化
- C++函数模板 模板实例化、具体化
- C++函数模板 模板实例化、具体化
- C++函数模板 模板实例化、具体化
- C++函数模板 模板实例化、具体化
- 函数模板和类模板的实例化和具体化
- 函数模板和类模板的实例化和具体化
- HashMap 散列初体验
- java访问liunx服务器
- JQuery EasyUI window 用法
- TP只保留年月日,不显示具体时间的写法
- Java XML中配置dubbo相关标签不能解析的问题
- C++函数模板的隐式实例化、显式实例化与显式具体化
- JTA深度历险-原理与实现
- python HTML格式发送邮件
- sql时间查询
- 数据结构----二叉树(交换子树)
- js面向对象编程:如何定义常量?
- java动态代理原理解析
- oracle存储函数
- textView相关知识