1. 实例化(instantiation)

实例化是指编译器使用函数(或者是类)模板为特定类型生成函数(类)定义。编译器不会为函数(或者类)模板生成定义,只有当我们为函数(或者类)模板指定了一个特定类型时,编译器才会生成。编译器为特定类型的函数(或者类)模板生成定义的行为被称为实例化。

template<typename T>
void Swap(T & a, T & b)
{
    T temp = a;
    a = b;
    b = temp;
}

void use_Swap(int & a, int & b)
{
    Swap(a, b);
}

举个例子,上面这段代码,通过反汇编的结果如下:

_Z4SwapIiEvRT_S1_:
	pushq	%rbp
	movq	%rsp, %rbp
	...     ...
	ret

Z4SwapIiEvRT_S1:对应的函数声明为void Swap(int&, int&),因此可以看到编译器实例化了Swap模板函数,这种实例化方法被称为隐式实例化。如果注释掉use_Swap函数,通过反汇编可以发现编译器不会实例化Swap函数,因为此时代码中只有Swap的模板函数,而没有为该函数指定一个特定类型的版本。

c++可以显示实例化一个模板函数(或者类)。

template void Swap<int>(int & a, int & b); /* 显示实例化Swap函数 */

2. 具体化(specialization)

使用模板能够极大的精简我们的代码量,尤其是在容器类或者一些通用函数中。但是,模板不能帮助我们解决所有问题。有时候我们需要针对特定的场景提供一个特殊的函数(或者类)定义,这个就是具体化。要注意实例化的具体化的区别,可以从编译器的角度来看这两者之间的区别,实例化是指编译器生成特定函数(或者类)定义;而具体化可以看做是一个特殊版本的用来生成函数(或者类)定义的方案,它只是一个方案,因此编译器不会生成定义。

struct ST;

/* 显示具体化的原型和定义应以template <> 开头 */
template <> void Swap<ST>(ST & st1, ST & st2);

上面是针对ST类型的Swap模板函数的一个显示具体化。模板类的实例化如下所示。

template<typename T>
class Swap {...};

template <> class Swap<ST> {...};

3. 部分具体化(partial specialization)

c++还允许部分具体化。template后面<>声明的是没有被具体化的参数类型。如果<>里面是空的,将导致显示具体化。

template<typename T1, typename T2>
class Swap {...};

template <typename T1> class Swap<T1, int> {...};

下面也是一种部分具体化的形式,表示该具体化版本只适用于T为原生指针的情况。

template<typename T>
class C<T*> {...};