[C++模板技术] 整数映射为类型

来源:互联网 发布:纽约州立石溪分校知乎 编辑:程序博客网 时间:2024/06/08 04:57

通过C++模板技术,我们可以将C++中的每个整数分别映射为一个不同的类型,其主要的方式如下:

template<int v>struct Int2Type{enum { value = v };};

其原理十分简单,即C++在编译期处理模板时,其会认为Int2Type<1>Int2Type<2>是两个完全不同的类型。

通过这个方法,我们主要的目的就是满足在编译时期,根据某个编译期常量,完成分派任务

通常来讲,这样的分派我们通过if等条件语句也可以完成,但是其具有一定的局限性,如:

template<typename T,bool isPolymorphic>class Container{public:void doSomething(T* obj){//...if (isPolymorphic){auto tmp = obj->clone();}else{auto tmp = new T(*obj);}//....}};

其中,Container是一个存储类型为T的系列元素的容器,并且,在Container内部我们提供了一个doSomething成员函数,其根据所提供的元素类型是否为一个多态类而完成是否调用clone()还是拷贝构造函数的分派任务

这样的写法看似很好,但是实际上其当容器内的内容并不是多态类时,总是无法通过编译的,如:

int main(){Container<int, false> c;int x = 1;c.doSomething(&x);return 0;}

像上面的用法总会导致编译错误,因为编译器会根据你提供的<int,false>模板参数,以及你对doSomething的调用实作出这样的成员函数:
void doSomething(int* obj){//...if (isPolymorphic){auto tmp = obj->clone();}else{auto tmp = new T(*obj);}//....}
然而,obj作为一个int*,其显然是无法提供clone()操作的,尽管我们不会进入第一个if分支,但是编译器必然会在此处报错而不让程序正常运行。

为了解决这个问题,将整数映射为类型的技术就发挥作用了,我们可以这样设计Container类:

template<int v>struct Int2Type{enum { value = v };};template<typename T,bool isPolymorphic>class Container{public:void doSomething(T* obj){//delegatingdoSomething(obj, Int2Type<isPolymorphic>());}private:void doSomething(T* obj, Int2Type<true>){//...auto tmp = obj->clone();//...}void doSomething(T* obj, Int2Type<false>){//...auto tmp = new T(*obj);//...}};
这样一来,我们利用重载机制,将true和false直接映射为两个不同的类型,通过函数重载匹配来进行分派任务,就可以使上面的代码正确通过编译、运行。

至于为什么这样就可以通过编译,实际也是根据模板类的成员函数的实作原则,当容器的模板参数为<int,false>时,在void doSomething(T* obj) 内部将会调用void doSomething(T*,Int2Type<false>)

于是,编译器就会生成void doSomething(T* obj) 与 doSomething(T*,Int2Type<false>)两份函数实体,至于 doSomething(T*,Int2Type<true>)其在程序的运行过程中根本就没有被调用,自然也就不会被编译器生成,更谈不上更深层的语法检查了。





原创粉丝点击