C++Primer Plus 第十四章代码重用:14.4.6 模板的具体化

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:类模板与函数模板很相似,因为可以有隐式实例化、显式实例化和显式具体化,它们统称为具体化(specialization)。模板以泛型的方式描述类,而具体化是使用具体的类型生成类声明。


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


14.4.6 模板的具体化

类模板与函数模板很相似,因为可以有隐式实例化、显式实例化和显式具体化,它们统称为具体化(specialization)。模板以泛型的方式描述类,而具体化是使用具体的类型生成类声明。

1.隐式实例化

到目前为止,本章所有的模板示例使用的都是隐式实例化(implicit instantiation),即它们声明一个或
多个对象,指出所需的类型,而编译器使用通用模板提供的处方生成具体的类定义:

ArrayTP<int,100>stuff;//implicit instantiation

编译器在需要对象之前,不会生成类的隐式实例化:

ArrayTP<double30>*pt;//a pointer,no object needed yet
pt =new ArrayTP<double,30>;//now an object is needed

第二条语句导致编译器生成类定义,并根据该定义创建一个对象。

2.显式实例化

当使用关键字template并指出所需类型来声明类时,编译器将生成类声明的显式实例化(explicitinstantiation)。声明必须位于模板定义所在的名称空间中。例如,下面的声明将 ArrayTP<string,100>声明
为一个类:

template class ArrayTP<string,100>;//generate ArrayTP<string,100> class

在这种情况下,虽然没有创建或提及类对象,编译器也将生成类声明(包括方法定义)。和隐式实例化-样,也将根据通用模板来生成具体化。

3.显式具体化

显式具体化(explicit specialization)是特定类型(用于替换模板中的泛型)的定义。有时候,可能需要在为特殊类型实例化时,对模板进行修改,使其行为不同。在这种情况下,可以创建显式具体化。例如,假设已经为用于表示排序后数组的类(元在加入时被排序)定义了一个板:

template <typename T>
class SortedArray
{
...// details omitted
}

另外,假设模板使用>运算符来对值进行比较。对于数字,这管用;如果T表示一种类,则只要定义了T:operator>()方法,这也管用;但如果T是出constchar *表示的字符串,这将不管用。实际上,模板倒是可以正常工作,但字符串将按地址(按照字母顺序)排序。这要求类定义使用strcmp(),而不是>来对值进行比较。在这种情况下,可以提供一个显式模板具体化,这将采用为具体类型定义的模板,而不是为泛型定义的模板。当具体化模板和通用模板都与实例化请求匹配时,编译器将使用具体化版本。
具体化类模板定义的格式如下:

template <>class Classname<specialized-type-name>(...};

早期的编译器可能只能识别早期的格式,这种格式不包括前缀template>>:

class Classname<specialized-type-name>..);

要使用新的表示法提供一个专供 const char *类型使用的 SortedArray 模板,可以使用类似于下面的代码:

template <>class SortedArray<const char char*>
{
...// details omitted
}

其中的实现代码将使用strcmp()(而不是>)来比较数组值。现在,当请求 const char *类型的 SortedArray模板时,编译器将使用上述专用的定义,而不是通用的模板定义:

SortedArray<int> scores;//use general definition
SortedArray<const char *>dates;//use specialized definition

4.部分具体化

C++还允许部分具体化(partialspecialization),即部分限制模板的通用性。例如,部分具体化可以给类型参数之一指定具体的类型:

//general template
template <class Tl,class T2> class Pair(...);
//specialization with T2 set to int
template <class Tl>class Pair<Tl,int>...);

关键字 template 后面的>声明的是没有被具体化的类型参数。因此,上述第二个声明将 T2 具体化为但 T1保持不变。注意,如果指定所有的类型,则内将为空,这将导致显式具体化:int,

/specialization with Tl and T2 set to int
template <>class Pair<intint>{...};

如果有多个模板可供选择,编译器将使用具体化程度最高的模板。给定上述三个模板,情况如下:

Pair<double,double>pl;//use general Pair template
Pair<doubleint>p2;//use Pair<Tl,int>partial specialization
Pair<intint>p3;/use Paircint,int>explicit specialization

也可以通过为指针提供特殊版本来部分具体化现有的模板:

template<class T>//general version
class Feeb{...};
template<class T*> //pointer partial specialization
class Feeb{...};//modified code
---


如果提供的类型不是指针,则编译器将使用通用版本;如果提供的是指针,则编译器将使用指针具体化版本:

Feeb<char> fbl;//use general Feeb template,T is char
Feeb<char *>fb2;//use Feeb T*specialization,Tis char

如果没有进行部分具体化,则第二个声明将使用通用模板,将T转换为char*类型。如果进行了部分具体化,则第二个声明将使用具体化模板,将T转换为char。
部分具体化特性使得能够设置各种限制。例如,可以这样做:

general template
template <class Tl,class T2,class T3> class Trio{...};//specialization withT3 set to T2
template <class Tl,class T2>class Trio<Tl,T2,T2>{...};//specialization with T3 and T2 set to Tl*template <class Tl> class Trio<T1,Tl*,T1*>{...};

给定上述声明,编译器将作出如下选择:

Trio<int,short,char*>tl;//use general template
Trio<intshort>t2://use Trio<T1,T2,T2>
Trio<char,char*,char*>t3;use Trio<Tl,Tl*,Tl*>

总结

提示:这里对文章进行总结:

例如:以上就是今天要讲的内容,14.4.6 模板的具体化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值