上节我们讲解了模板的显示具体化(Explicit Specialization),本节我们讲解模板的显示实例化(Explicit Instantiation),具体化和实例化是两个不同的概念。
为了搞清两个概念的区别,首先需要明确的是,在代码中包含函数模板本身不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例(Instantiation)。例如对于前面的 Swap(),函数调用Swap(m, n)将导致编译器生成 Swap() 的一个实例,该实例使用 int 类型。
模板并非函数定义,但使用 int 的模板实例是函数定义,这种实例化方式被称为隐式实例化(Implicit Instantiation),因为编译器之所以知道需要进行定义,是由于程序调用 Swap() 函数时提供了 int 类型的实参。
最初,编译器只能通过隐式实例化来让函数模板生成函数定义,但现在的 C++ 编译器还允许显示实例化,这意味着可以直接命令编译器创建特定的实例。
显式实例化可以在函数声明中指定,例如对于上节的 Max(),可以使用下面的声明来生成一个 int 类型的实例:
这就是模板的显示实例化。实现了这种特性的编译器看到上述声明后,将使用 Max() 模板生成一个 int 类型的实例。也就是说,该声明的意思是“使用 Max() 模板生成一个 int 类型的函数定义”。
再来对比一下模板的显式具体化,它使用下面两个等价的声明之一:
这些声明的意思是:不要使用 Max() 模板来生成函数定义,而应该使用专门为 int 类型显式定义的函数定义。这些原型必须有自己的函数定义。
显式具体化在关键字 template 后面要跟<>,而显式实例化没有。
另外需要注意的是,在同一个文件中使用同一种类型的显式实例化和显式具体化将会出错,因为这样做在函数调用时会产生二义性,编译器不知道选择哪一个版本。