函数模板是C++新增的一种性质,它允许只定义一次函数的实现,即可使用不同类型的参数来调用该函数。这样做可以减小代码的书写的复杂度,同时也便于修改。但是,在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例(instantiation)。
1 实例化
实例化有两种形式,分别为显式实例化和隐式实例化。模板并非函数定义,实例式函数定义。
1.1 显式实例化(explicit instantiation)
显式实例化意味着可以直接命令编译器创建特定的实例,有两种显式声明的方式。
比如存在这么一个模板函数
template <typename T>
void Swap(T &a, T &b)
第一种方式是声明所需的种类,用<>符号来指示类型,并在声明前加上关键词template,如下:
template void Swap<int>(int &, int &);
第二种方式是直接在程序中使用函数创建,如下:
Swap<int>(a,b);
显式实例化直接使用了具体的函数定义,而不是让程序去自动判断。
1.2 隐式实例化(implicit instantiation)
隐式实例化比较简单,就是最正常的调用,Swap(a,b),直接导致程序生成一个Swap()的实例,该实例使用的类型即参数a和b的类型,编译器根据参数来定义函数实例。
2 具象化(显式)
思考这么一个问题,当前的Swap模板交换输入的两个对象,可能式基本类型也可能式自定义类。如果有这么一个需求,需要交换自定义类里的某一个属性而不是整个类,那么Swap模板就不可用,因为Swap模板交换的是整个类。
显式具体化将不会使用Swap()模板来生成函数定义,而应使用专门为该特定类型显式定义的函数类型。有两种定义形式,如下,其中job为用户自定义类
template <> void Swap(job &a, job &b)
template <> void Swap<job>(job &a, job &b)
显式具体化在声明后,必须要有具体的实现,这是与显示实例化不同的地方。
3 举例
下面通过一个程序来观察实例化和具体化,加深理解。
/*************************************************************************
> File Name: array.cpp
> Author:
> Mail:
> Created Time: Sat 05 Aug 2017 01:20:31 AM PDT
************************************************************************/
#include<iostream>
#include<string>
using namespace std;
struct job
{
string name;
int salary;
job(string _name,int _salary):name(_name),salary(_salary){};
};
//template prototype
template <typename T>
void Swap(T &a, T &b){
T temp;
temp = a;
a = b;
b = temp;
}
//explict specialization for job 显式具体化
template <> void Swap(job &a, job &b)
{
int temp;
temp = a.salary;
a.salary = b.salary;
b.salary = temp;
}
template void Swap<int>(int &, int &);
int main()
{
char a = 'a', b = 'b';
cout<<"a: "<<a<<" ; b: "<<b<<endl;
Swap(a,b); //1 implicit template instantiation for char 隐式实例化
cout<<"a: "<<a<<" ; b: "<<b<<endl;
int c = 1, d = 2;
cout<<"c: "<<c<<" ; d: "<<d<<endl;
Swap(c,d); //2 use explicit template instantiation for int 显式实例化
cout<<"c: "<<c<<" ; d: "<<d<<endl;
Swap<int>(c,d); //3 use explict template instantiation for int 显式实例化
cout<<"c: "<<c<<" ; d: "<<d<<endl;
job e("lucy",100), f("bob",200);
cout<<"lucy: "<<e.name<<" "<<e.salary<<" ; bob: "<<f.name<<" "<<f.salary<<endl;
Swap(e,f); //use explict specialization for job 调用显式具体化
cout<<"lucy: "<<e.name<<" "<<e.salary<<" ; bob: "<<f.name<<" "<<f.salary<<endl;
}
➜ cpptest ./a.out
a: a ; b: b
a: b ; b: a
c: 1 ; d: 2
c: 2 ; d: 1
c: 1 ; d: 2
lucy: lucy 100 ; bob: bob 200
lucy: lucy 200 ; bob: bob 100
备注:隐式实例化和显式实例化和显式具体化统称为具体化,它们的相同在于都用了具体类型的函数定义,而不是通用描述。