设一个模板具有模板参数T,表示C++中的某种类型。有些情况下,随着T所取类型的不同,该模板会做不同的处理。在设计该模板时,我们需要了解T的具体信息。在编写一个具有模板参数T的类模板时,有时需要了解T所取类型的具体信息,以做不同的处理。这是一个棘手的问题,因为C++语言只有很少几个运算符能够处理“类型”:sizeof、dynamic_cast以及typeid。和我们想要获取的类型信息相比,这些运算符提供的信息太少。运算符sizeof只能够求取一个类型的对象所占用的内存空间。对于含有虚函数的类,dynamic_cast可被用来判断一个对象是否具有某个类型,但是这个运算符只能施加到一个指针(或引用),不能施加到一个类型。运算符typeid倒是适用于所有类型(或者这些类型的对象),但是它只能获得一个类型的名字信息。
既然C++本身不能够提供足够详细的信息,我们可以使用类模板特化技术,设计专门的类模板来提供所需信息,这种方法被称为类型分类(typeclassification)技术。我们以一个具体的例子来说明这种技术的原理。设想这样一个任务:模板参数T是指针类型、引用类型或者数组类型中的某一种,我们需要判断T究竟是其中的哪一个。如果是指针类型,需要知道该指针所指的类型,并将其命名为baseT。还需要知道该类型最终涉及哪个C++基本类型,并将其命名为bottomT。比如,对于指针类型int * *,baseT为int *,而bottomT为int。类似地,对于引用类型,baseT表示所引用的类型,bottomT表示该引用类型最终涉及哪个C++基本类型。比如,对于类型double * &,baseT为double*,bottomT为double。对于数组类型,baseT表示数组元素的类型,bottomT表示该数组类型最终涉及哪个C++基本类型。比如,设有数组类型typedef int * arrayType[100],baseT为int *,而bottomT为int。类模板特化技术可解决这个问题。如代码段,主类模板定义了一组枚举常量,每个枚举常量的取值表示模板参数T是否具有对应的类别。比如,IsPtrT为1则表示T是指针类型,为0则表示T不是指针类型。
#ifndef TYPECLASSIFICATION_H
#define TYPECLASSIFICATION_H
// Type Classification 类型分类技术
/**
* sizeof() 能够求取一个类型的对象所占用的内存空间
* dynamic_cast 对于含有虚函数的类,可被用来判断一个对象是否具有某个类型,但是这个运算符只能施加到一个指针(或引用),不能施加到一个类型
* typeid() 适用于所有类型(或者这些类型的对象),但是它只能获得一个类型的名字信息
*/
// 主类模板
template <typename T>
class TypeInfo{
public:
enum{IsPtrT = 0,IsRefT = 0,isArrayT = 0};
typedef T baseT;
typedef T bottomT;
};
// 特化类模板==>指针
template<typename T>
class TypeInfo<T*>{
public:
enum{IsPtrT = 0,IsRefT = 0,isArrayT = 0};
typedef T baseT;
typedef typename TypeInfo<T>::bottomT bottomT;
};
//特化类模板==》引用
template<typename T>
class TypeInfo<T&>
{
public:
enum{IsPtrT = 0,IsRefT = 0,isArrayT = 0};
typedef T baseT;
typedef typename TypeInfo<T>::bottomT bottomT;
};
// 特化类模板==》数组
template <typename T,size_t N>
class TypeInfo<T[N]>
{
public:
enum{IsPtrT = 0,IsRefT = 0,isArrayT = 0};
typedef T baseT;
typedef typename TypeInfo<T>::bottomT bottomT;
};
#endif // TYPECLASSIFICATION_H
这种使用模板特化技术来描述模板参数T的类型信息的技术即被称为类型分类(type classification)。类型分类技术和traits技术很相似:都是利用模板特化技术描述一个类型的具体信息。但是二者的侧重点有所不同,类型分类侧重于描述一个类型的类别信息,比如它是否是指针、数组等,而traits技术侧重于描述一个类型的具体信息,比如浮点数的表示范围、精度等。