参考C++ Primer Plus(中文第五版)P246--258关于函数模板的材料,总结如下:
结合原书中以下代码分析:
//程序清单8.13
// twoswap.cpp -- specialization overrides a template
#include <iostream>
template <class Any>
void Swap(Any &a, Any &b);
struct job
{
char name[40];
double salary;
int floor;
};
// explicit specialization
template <> void Swap<job>(job &j1, job &j2);
void Show(job &j);
int main()
{
using namespace std;
cout.precision(2);
cout.setf(ios::fixed, ios::floatfield);
int i = 10, j = 20;
cout << "i, j = " << i << ", " << j << ".\n";
cout << "Using compiler-generated int swapper:\n";
Swap(i,j); // generates void Swap(int &, int &)
cout << "Now i, j = " << i << ", " << j << ".\n";
job sue = {"Susan Yaffee", 73000.60, 7};
job sidney = {"Sidney Taffee", 78060.72, 9};
cout << "Before job swapping:\n";
Show(sue);
Show(sidney);
Swap(sue, sidney); // uses void Swap(job &, job &)
cout << "After job swapping:\n";
Show(sue);
Show(sidney);
return 0;
}
template <class Any>
void Swap(Any &a, Any &b) // general version
{
Any temp;
temp = a;
a = b;
b = temp;
}
// swaps just the salary and floor fields of a job structure
template <> void Swap<job>(job &j1, job &j2) // specialization
{
double t1;
int t2;
t1 = j1.salary;
j1.salary = j2.salary;
j2.salary = t1;
t2 = j1.floor;
j1.floor = j2.floor;
j2.floor = t2;
}
void Show(job &j)
{
using namespace std;
cout << j.name << ": $" << j.salary
<< " on floor " << j.floor << endl;
}
观察可知,在仅有的一个twoswap.cpp文件中,我们在main函数之前声明了一个常规模板函数,即:
template <class Any>
void Swap(Any &a, Any &b)
还声明了一个显示具体化的模板函数:
// explicit specialization
template <> void Swap<job>(job &j1, job &j2);
void Show(job &j);
在main函数之后,接着定义了这两个函数。
在这里,有必要讲一下,如果我们在同一个文件中,定义了三个同名的函数,其中一个是常规模板函数,一个是显示具体化的模板函数,一个是常规的非模板函数。那么之间如果存在覆盖的话,优先级是怎样的呢? 书中告诉了我们答案,它说在C++标准中,具体化的模板函数将覆盖常规模板函数,而常规的非模板函数将覆盖具体化的模板函数和常规模板函数。
c++标准还规定了具体化的原型和定义都必须是以template<>打头,通过名称来指出类型。
带代码中包含模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例(instantiation)。模板并非函数定义,但是使用特定类型的实例是函数定义。这种实例化方式被称为隐式实例化(implicit instantiation),就是说:编译器在遇到模板函数的声明和定义代码时,并没有给出一个实际的实例定义,它只是获得了关于一个模板函数的介绍,而在遇到调用特定类型的模板函数实例时,编译器才决定以特定类型代替模板函数的模板类型参数,并给出特定类型的实例化定义。哪照这样说,如果我们不调用特定类型的模板函数,模板也就不会实例化了。
但是,现在我们也可以是一个模板函数显示实例化(explicit instantiation),就是说我们可以直接命令编译器创建特定的实例,方式为:
template <> void 函数名<特定类型>(特定类型参数列表)
如:
template void Swap<job>(job &j1, job &j2)
这里注意,显示实例化和显示具体化的意思是不一样的!!!区别在于:
1.显示具体化(explicit specialization)是针对某种特定类型,需要使用与模板函数定义中不同的特定算法时,需要对模板显示具体化,格式例子如下:
template <> void Swap<job>(job &j1, job &j2) // explicit specialization 显示具体化
2.显示实例化(explicit instantiation)是实现模板函数定义的实例,格式例子如下:
template void Swap<job>(job &j1, job &j2) // explicit instantiation 显示实例化
注意显示具体化的声明和定义中代码,在template后面都有一个尖括号<>,而显示实例化都没有。
实际上,如果对同一个模板函数的