代码改变世界

泛型:常数映射为类型的一个利用

2010-03-06 20:12  听雨到天明  阅读(318)  评论(0编辑  收藏  举报

在说明这个主题之前,可以先来看一下下面这个代码

template<typename T>
void DoSomethins(T type, bool bTrue)
{
if (bTrue)
{
   type.DoThat();
}
else
{
   type.Do();
}
}

这个模板函数根据输入的参数bTrue来区分调用方式,如果为true,则调用type.DoThat(),否则调用type.Do()。

如果T始终是包含了DoThat()方法和Do()方法,则这个模板函数可以按照俺们的预期,运行的非常良好。

但是,事实始终不掌握在俺们手里啊。客户写了一个新的类X,这个类只包含了DoThat()方法,显然用户在调用这个函数的时候,会这么写 DoSomethins(x, true)。事情到了这一步,悲剧就开始了,不妨写几个类到编译器中测试下看看,编译器会毫不留情的抛了一个错误出来。。。

为什么错误呢?因为编译器在编译这个模板函数的时候,会按照写的代码编译,假如bTrue等于True就调用x的DoThat()方法,否则调用Do()方法,但是回头一看,这个X类是客户写的,客户只提供了一个DoThat()方法,所以一编译到了type.Do();这里,编译器就会告诉你,找不到Do()这个方法。。

那么,自然而然的,我们会祈祷编译器,你智能点吧,明显人家传的是True,那False分支用不到你就不要去编译了吧。。

事实证明,编译器听不到我们的祈祷。

那么这个时候,利用模板的一个特性“从未被使用到的模板函数,不会被编译”和本主题,将常数映射为类型就该联合出马了

常数映射为类型的结构可以如下所示:

template<int V>
struct Int2Type
{
enum {tpe = V};
};

这样 Int2Type<True> 和 Int2Type<False>就是两种类型了。这个时候,再把true分支和false分支分别提出来放到另外的两个模板函数中了。如下所示

template<typename T>
void DoWhat(T type, Int2Type<True> i2t)
{

....执行True分支的代码....
}


template<typename T>
void DoWhat(T type, Int2Type<False> i2t)
{
....执行False分支的代码....
}

然后再利用编译时多态,将DoSomethins改成如下所示即可。

template<typename T>
void DoSomethins(T type, bool bTrue)
{
     DoWhat(type, Int2Type<bTrue>); 
}

这样分拆的三个函数相比起最原始的函数,是不是显的更为优雅?