模板的使用:Promotion Traits( 类型提升之特征萃取)

一、需求引入

让我们先来看一个函数模板

template<typename T> 
Array<T> operator+ (Array<T> const&, Array<T> const&); 

这很好,但由于语言允许我们将一个  char  和一个  int  相加,我们十分希望诸如此类的混合操作  也能实施于  arrays  身上。这么一来我们就必须决定新版本的回返类型(return type)应该是什么: 
 
template<typename  T1,  typename  T2> 
Array<???> operator+ (Array<T1> const&, Array<T2> const&);


问题是Array<???> 到底应该是什么类型呢?


promotion traits template 使我们能够以如下方式填充上述声明中的问号: 
 
template<typename T1, typename T2>  
Array<typename  Promotion<T1,  T2>::ResultT> 

operator+ (Array<T1> const&, Array<T2> const&); 


或使用如下方式: 
template<typename T1, typename T2> 
typename Promotion<Array<T1>, Array<T2> >::ResultT 
operator+ (Array<T1> const&, Array<T2> const&); 


此种想法在于为   template  Promotion 提供大量特化版本,以创建出一个满足我们所需的  type function。另一个应用由   max() template  激发出来:当我们希望指出类型不同的两数值中的较大  者时,应该采用「较大」的那个类型(2个类型中更加强大的类型)


二、实现

第一步:声明typename  Promotion主模板

由于template 并不存在真正的泛型定义。最好的选择是:别去定义  primary class template(主模 板): 
template<typename T1, typename T2> 
class Promotion; 


第二步:定义一个具有在2个类型中选择某一个类型方法的模板

//主模板(未定义):根据第一个实参来决定:是选择第二个实参,还是选择第三个模板

template<bool C, typename Ta, typename Tb> 

class IfThenElse; 
 
//  局部特化: true 的话选择第二个实参
template<typename  Ta,  typename  Tb> 
class IfThenElse<true, Ta, Tb> { 

public: 
typedef Ta ResultT; 
}; 
 
// 局部特化: false 的话选择第三个实参
template<typename  Ta,  typename  Tb> 
class IfThenElse<false, Ta, Tb> { 

public: 
typedef Tb ResultT; 
}; 


第三步:定义第一步中声明的模板

template<typename T1, typename T2> 
class Promotion { 
public: 

//typedef一个类型
typedef typename 
IfThenElse<(sizeof(T1)>sizeof(T2)) ,  //第一个参数

T1,                                                    //第二个参数
typename IfThenElse<(sizeof(T1)<sizeof(T2)), T2, void >::ResultT  //第三个参数
>::ResultT
ResultT; 
}; 


第四步:针对Promotion 进行一些局部特化

//两个参数相同的局部特化版本

template<typename T> 
class Promotion<T,T> { 

public: 
typedef T ResultT; 
}; 


第五步:针对普通类型的 全特化 版本

可以利用宏,减少源代码的数量

#define MK_PROMOTION(T1,T2,Tr)      \ 

template<> class Promotion<T1, T2> {  \ 

public:                                                  \

          typedef Tr ResultT;                     \

};                                                          \ 

template<> class Promotion<T2, T1> {  \ 

public:                                                  \ 

          typedef Tr ResultT;                     \ 
}; 


第六步:添加一些普通类型的全特化提升

MK_PROMOTION(bool, char, int) 
MK_PROMOTION(bool,  unsigned  char,  int) 
MK_PROMOTION(bool, signed char, int) 
//... 

这种方式相当直截了当,却需要列举数十个可能组合。


第七步:为了一般类型提供提升的规则(除了基本类型和枚举类型之外)

以先前的  Array  为例:

template<typename T1, typename T2> 
class Promotion<Array<T1>, Array<T2> > { 
public: 
typedef Array<typename Promotion<T1,T2>::ResultT> ResultT; 
}; 
 

//针对array的 2个参数相同的 局部特化版本
template<typename T> 
class Promotion<Array<T>, Array<T> > { 
public: 
typedef Array<typename Promotion<T,T>::ResultT> ResultT; 
}; 


最后这个偏特化版本有若干特别值得注意的地方。 乍见之下, 好像先前针对类型一致 (identical types)而设计的局部特化版本(Promotion<T,T>)已经处理了这种情况。不幸的是,就特化程度而言,Promotion<T,T>和  Promotion<Array<T1>, Array<T2> > 

是一样的。为避免选择  templates 时发生模棱两可(歧义)情况,我们增加了最后一个局部特化版本,它比前面2个局部特化版本更加特殊化。


当更多  types  被加入时,为了使  promotion(类型晋升)有意义,我们需要为  Promotion  template 加入更多的全特化版本和局部特化版本。


三、使用

Promotion  的 使用方法在需求引入部分已经提到了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值