曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3232|回复: 0
打印 上一主题 下一主题

[函数模板]实例化和具体化

[复制链接]

716

主题

734

帖子

2946

积分

超级版主

Rank: 9Rank: 9Rank: 9

积分
2946
跳转到指定楼层
楼主
发表于 2013-12-18 14:10:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
实例化与具体化是两个不同概念术语。

首先应该明确,在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。

编译器使用模板为特定类型生成函数定义时,得到的是模板实例(instantiation)。例如,有下面的模板定义:
  1. template <class T>          // 模板
  2. void Swap(T &, T &);
复制代码
当函数调用 Swap(i, j) 时( i 和 j 为 int 类型),将导致编译器生成 Swap() 的一个实例。模板并非函数定义,但使用 int 的模板实例是函数定义。这种实例化方式被称为隐式实例化(implicit instantiation)

C++ 不但可以隐式实例化,还允许显式实例化(explicit instantiation)。这意味着,可以直接命令编译器创建特定的实例,如 Swap<int>() 。其语法是,声明所需的种类 --- 用 <> 符号指示类型,并在声明前加上关键字 template
  1. template void Swap<int>(int, int);  //显式实例化
复制代码
该声明的意思是,使用 Swap() 模板生成 int 类型的函数定义。

与显式实例化不同的是,显式具体化使用下面两个等价的声明之一:
  1. template <> void Swap<int> (int &, int &);   // 显式具体化
  2. template <> void Swap(int &, int &);  // 显式具体化
复制代码
区别在于:这些声明的意思是“不要使用 Swap() 模板来生成函数定义,而应使用专门为 int 类型显式地定义的函数定义。” 这些原型必须有自己的函数定义。显式具体化声明在关键字 template 后包含 <>,而显式实例化没有。

注意:试图在同一个文件(或转换单元)中使用同一种类型的显式实例和显式具体化将出错。

还可以通过在程序中使用函数来创建显式实例化:
  1. template <class T>
  2. T Add(T a, T b)
  3. {
  4.    return a + b;
  5. }
  6. int m = 6;
  7. double x = 10.2;
  8. cout << Add<double>(x, m) << endl;  //显式实例化
复制代码
这里的模板与函数调用 Add(x, m) 不匹配,因为该模板要求两个参数的类型要相同。但通过使用 Add<double>(x, m),可强制为 double 类型实例化,并将参数 m 强制转换为 double 类型,以便与函数 Add<double>(double, double) 的第 2个参数匹配。

隐式实例化、显式实例化和显式具体化统称为具体化( specialization )。它们的相同之处在于,它们表示的都是使用具体类型的函数定义,而不是通用描述。

引入显式实例化后,必须使用新的语法 --- 在声明中使用前缀 template 和 template<> ,以区分显式实例化和显式具体化。

下面的代码片段总结了这些概念:
[C++] 纯文本查看 复制代码
...
template <class T>
void Swap (T &, T &);  // 模板原型

template <> void Swap<job>(job &, job &);   // 对 job 的显式具体化
int main(void)
{
template void Swap<char>(char &, char &); // 对 char 的显式实例化
short a, b;
...
Swap(a,b);    // 对 short 的隐式实例化
job n, m;
...
Swap(n, m);   // 对 job 使用显式具体化
char g, h;
...
Swap(g, h);  // 对 char 使用显式实例化
...
}

编译器看到 char 的显式实例化后,将使用模板定义来生成 Swap() 的 char 版本。对于其他 Swap() 调用,编译器根据函数调用中的实际使用参数,生成相应的版本。例如,当编译器看到函数调用 Swap(a, b) 后,将生成 Swap() 的 short 版本,因为这两个参数的类型都是 short 。当编译器看到 Swap(n, m) 后,将使用为 job 类型提供的独立定义(显式具体化)。当编译器看到 Swap(g, h) 后,将使用处理显式实例化时生成的模板具体化。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-4-30 08:06 , Processed in 0.078309 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表