C++函数新特性——函数模版

来源:互联网 发布:淘宝商城卖家出售 编辑:程序博客网 时间:2024/06/06 00:00

函数模版


函数模版是通用的函数描述,使用泛型来定义函数,其中的泛型可用具体的类型(如int或double)来代替。通过将类型作为参数传递给模版,可使编译器生成该类型的函数。

下面演示一个最简单的函数模版:

//交换两数据的值template<typename T>void Swap(T &a, T &b){    T temp;    temp = a;    a = b;    b = temp;}

如果采用以下调用:

int a=10;int b=20;Swap(a,b);

这将代表调用下面这个函数:

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

Swap()函数接受了两个int参数,因此编译器生成该函数的int版本,也就是说用int替换所有的T。

调用函数模版必须使用相同的类型,否则模版将无法识别不同的类型而导致编译错误


显式具体化

显式具体化也是基于函数模版的,只不过在函数模版的基础上,添加一个专门针对特定类型的、实现方式不同的具体化函数。

对于有些特殊类型,可能不适合模版实现,需要重新定义实现。此时可以使用显式具体化(explicit specialization)
以上面的Swap()模版为例,假定有如下结构体:

struct job{    char[20] name;    double salary;};

如果采用Swap()函数模版将交换两个结构体。但如果只想交换其中的一部分,比如salary,而不交换name,则可以通过使用显式具体化。

//结构体struct Job{    char[20] name;    double salary;};//函数模版template<typename T>void Swap(T &a, T &b){    T temp;    temp = a;    a = b;    b = temp;}//显式具体化templete<> void Swap<Job>(Job &a,Job &b){    int temp;    temp = a.salary;    a.salary = b.salary;    b.salary = temp;}

编译器会优先选择显式具体化的版本,交换结构体的salary,而非交换两个结构体。

编译器对三种原型的选择

对于交换结构体Job的非模版函数、函数模版和具体化的原型:

//非模版函数void Swap(Job &,Job &);//函数模版template <typename T>void Swap(T &,T &);//显式具体化template<>void Swap<Job>(Job &,Job &);

在有多个原型时,编译器在选择原型时,非模版版本优先于显式具体化和模版版本,而显式具体化优先于使用模版生成的版本


显式实例化

当显式实例化模版时,在使用模版之前,编辑器根据显式实例化指定的类型生成模版实例。

template void Swap<int>(int&,int&);

显式实例化只需要声明,不需要重新定义。编译器会根据模版来实现实例声明和实例定义。
当然也可以直接调用 Swap<int>(a,b);

显式具体化和显式实例化的区别

//显式具体化template<>void Swap<Job>(Job &,Job &);//或template<>void Swap(Job &,Job &);//显式实例化template void Swap<int>(int &,int &);

显式具体化不仅要声明,还要给出定义;
显式实例化只需要声明,不需要给出定义。