返回   cpper编程论坛 > C/CPP/TMP/GP
注册账号 论坛帮助 会员列表 日历事件 搜索 今日新帖 标记版面已读

回复
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2005-02-04
高级会员
 
注册日期: 2004-12-06
帖子: 142
哑巴英语 正向着好的方向发展
默认 一个类似DoubleDispatch的实现

看完了第三章。想起ChenA的那个问题。正好需要阶段性的总结。就实现一个比较完全的DoubleDispatch看看。也作为作业练习下。
基本的,客户手动修改越少越好,仍然用函数,而不是functor。
尽量尊重非MP的习惯。

首先是前三章的工具,这里用到的。主要是TypeList列表和相关的类型操作。
代码:
//判断T是否base of U #define SUPERSUBCLASS(T,U) \ (Conversion<const U*,const T*>::exists\ &&!Conversion<const T*, const void*>::sameType) //判断T U是否可以转换 template<class T,class U> struct Conversion { protected: typedef char Small; class Big{char dummy[2];}; static Small Test(U); static Big Test(...); static T MakeT(); public: enum{exists=sizeof(Test(MakeT()))==sizeof(Small)}; enum{sameType=false}; }; template<class T> struct Conversion<T,T> { public: enum{exists=true}; enum{sameType=true}; }; //从T,U中选取 template<bool flag,typename T,typename U> struct Select { typedef T Result; }; template<typename T,typename U> struct Select<false,T,U> { typedef U Result; }; //TypeList和相关的工具 class NullType{};//不能是任何类的基类 template<class T,class U> struct TypeList { typedef T Head; typedef U Tail; }; //Length获取TList的长度 template<class TList> struct Length; template<> struct Length<NullType> { enum{value=0}; }; template<class T,class U> struct Length<TypeList<T,U> > { enum{value=1+Length<U>::value}; }; //IndexOf 获取T在TList中的序号 template<class TList,class T> struct IndexOf; template<class T> struct IndexOf<NullType,T> { enum{value=-1}; }; template<class T,class Tail> struct IndexOf<TypeList<T,Tail>,T> { enum{value=0}; }; template<class Head,class Tail,class T> struct IndexOf<TypeList<Head,Tail>,T> { private: enum{v1=IndexOf<Tail,T>::value}; public: enum{value=v1==-1?-1:1+v1}; }; //Replace将TList中的第一个T置换为U template<class TList,class T,class U> struct Replace; template<class T,class U> struct Replace<NullType,T,U> { typedef NullType Result; }; template<class T,class Tail,class U> struct Replace<TypeList<T,Tail>,T,U> { typedef TypeList<U,Tail> Result; }; template<class Head,class Tail,class T,class U> struct Replace<TypeList<Head, Tail>, T, U> { typedef TypeList<Head,typename Replace<Tail,T,U>::Result> Result; }; //Erase 从TList中删除第一个T template<class TList,class T> struct Erase; template<class T> struct Erase<NullType,T> { typedef NullType Result; }; template<class T,class Tail> struct Erase<TypeList<T,Tail>,T> { typedef Tail Result; }; template<class Head,class Tail,class T> struct Erase<TypeList<Head, Tail>, T> { typedef TypeList<Head,typename Erase<Tail,T>::Result> Result; }; //MostDerived 从TList获取最大的Derived of T template<class TList,class T> struct MostDerived; template<class T> struct MostDerived<NullType,T> { typedef T Result; }; template<class Head,class Tail,class T> struct MostDerived<TypeList<Head,Tail>,T> { private: typedef typename MostDerived<Tail,T>::Result T1; public: typedef typename Select<SUPERSUBCLASS(T1,Head),Head,T1>::Result Result; }; //DerivedToFront 将TList调整为继承 偏序 template<class T> struct DerivedToFront; template<> struct DerivedToFront<NullType> { typedef NullType Result; }; template<class Head,class Tail> struct DerivedToFront<TypeList<Head,Tail> > { private: typedef typename MostDerived<Tail,Head>::Result T1; typedef typename Replace<Tail,T1,Head>::Result L1; public: typedef TypeList<T1,L1> Result; }; //NoDuplicates 将TList重复的删除 template<class TList> struct NoDuplicates; template<> struct NoDuplicates<NullType> { typedef NullType Result; }; template<class Head,class Tail> struct NoDuplicates<TypeList<Head,Tail> > { private: typedef typename NoDuplicates<Tail>::Result L1; typedef typename Erase<L1,Head>::Result L2; public: typedef TypeList<Head,L2> Result; };
为了将指定的T的Supers从TypeList中提取,以及在两个TypeList中查找符合关系的两个Type,自己写了几个小工具。
代码:
//ReserveSupers 从TList中只保留T和T的基类 template<class TList,class T> struct ReserveSupers; template<class T> struct ReserveSupers<NullType,T> { typedef NullType Result; }; template<class Head,class Tail,class T> struct ReserveSupers<TypeList<Head, Tail>,T> { private: typedef typename ReserveSupers<Tail,T>::Result L1; typedef TypeList<Head,L1> L2; public: typedef typename Select<SUPERSUBCLASS(Head,T),L2,L1>::Result Result; }; //Supers 从TList中获取T的supers,偏序 template<class TList,class T> struct Supers { private: typedef typename NoDuplicates<TList>::Result L1; typedef typename ReserveSupers<L1,T>::Result L2; public: typedef typename DerivedToFront<L2>::Result Result; }; //FindIf在TList中寻找符合Cond<T,U>::value==true的U //结果value指示找到否,Result指示类型 template<class TList,class T,template<class T1,class T2> class Cond> struct FindIf; template<template<class T1,class T2> class Cond> struct FindIf<NullType,NullType,Cond>//空表中找空认为成功 { enum{value=true}; typedef NullType Result; }; template<class TList,template<class T1,class T2> class Cond> struct FindIf<TList,NullType,Cond>//空元素和其他匹配,总是成功的 { typedef NullType Result; enum{value=true}; }; template<class T,template<class T1,class T2> class Cond> struct FindIf<NullType,T,Cond>//空表中总是找不到非空元素 { typedef T Result; enum{value=false}; }; template<class Head,class Tail,class T,template<class T1,class T2> class Cond> struct FindIf<TypeList<Head,Tail>,T,Cond> { typedef typename Select<Cond<T,Head>::value, Head,typename FindIf<Tail,T,Cond>::Result>::Result Result; enum{value=Cond<T,Head>::value||FindIf<Tail,T,Cond>::value}; }; //FindPairIf 获得符合条件的T1和T2在TList1中和TList2中 //返回Result1和Result2中(总会成功 至多 NullType NullType) template<class TList1,class TList2,template<class T1,class T2> class Cond> struct FindPairIf; template<class TList2,template<class T1,class T2> class Cond> struct FindPairIf<NullType,TList2,Cond> { typedef NullType Result1; typedef NullType Result2; }; template<class Head,class Tail,class TList2,template<class T1,class T2> class Cond> struct FindPairIf<TypeList<Head,Tail>,TList2,Cond> { private: typedef FindIf<TList2,Head,Cond> T1; typedef FindPairIf<Tail,TList2,Cond> T2; public: typedef typename Select<T1::value,Head,typename T2::Result1>::Result Result1; typedef typename Select<T1::value,typename T1::Result,typename T2::Result2>::Result Result2; };
再这两堆工具的帮助下,实现了一个double dispatch的工具。(不知道怎么称呼这种东西,反正觉得叫类似乎不妥。)
代码:
//调度用的工具 template< class L1,class L2,template<class,class> class Cond,//在L1和L2中,以及判断需disp的条件Cond class DispT,//dispT类型 template<class,class,class> class DispP//类型产生者 > struct Dispatcher2 { public: Dispatcher2() { TableFiller<L1,L2> filltable; filltable(); } static DispT GetDisp(int i,int j){return disp_table[i][j];} public: template<class T> struct InnerID1{enum{value=IndexOf<L1,T>::value};}; template<class T> struct InnerID2{enum{value=IndexOf<L2,T>::value};}; private: static DispT disp_table[Length<L1>::value][Length<L2>::value]; private: //内部使用的模板类 //获取碰撞类型 template<class T,class U> struct Pair { private: typedef FindPairIf<typename Supers<L1,T>::Result,typename Supers<L2,U>::Result,Cond> T1; public: typedef typename T1::Result1 R1; typedef typename T1::Result2 R2; }; //填写一行的functor template<class TList,class T> struct LineFiller; template<class T> struct LineFiller<NullType,T>{void operator()(){}}; template<class Head,class Tail,class T> struct LineFiller<TypeList<Head,Tail>,T> { void operator()() { int i=IndexOf<L1,T>::value; int j=IndexOf<L2,Head>::value; DispP<typename Pair<T,Head>::R1,typename Pair<T,Head>::R2,DispT> p; disp_table[i][j]=p(); LineFiller<Tail,T> fillline; fillline(); } }; //填写整个表 template<class TList1,class TList2> struct TableFiller;//声明 template<class TList2> struct TableFiller<NullType,TList2>{void operator()(){}};//结束条件 template<class Head,class Tail,class TList2>//递归过程 struct TableFiller<TypeList<Head,Tail>,TList2> { void operator()() { LineFiller<TList2,Head> fillline; fillline(); TableFiller<Tail,TList2> filltable; filltable(); } }; }; template< class L1,class L2,template<class,class> class Cond,//在L1和L2中,以及判断需disp的条件Cond class DispT,//dispT类型 template<class,class,class> class DispP//类型产生者 > DispT Dispatcher2<L1,L2,Cond,DispT,DispP>::disp_table[Length<L1>::value][Length<L2>::value];
最后看使用的代码。要自己手动填写类型表,自己实现virtual的ID1和ID2(当然它的具体实现属于Dispatch),自己提供一个Disp的类型,判断是否冲突的方法,产生Disp的方法。
代码:
//这里是用户要填写的地方 class Base; class A; class B; class C; class D; typedef TypeList<A, TypeList<B, TypeList<D, TypeList<D, TypeList<C, TypeList<Base,NullType> > > > > > Colliders;//将Collider的类型手动填入这个表中可以重复但不要遗漏,Base可以不用写入 //定义了两个类型表//也可以放入Dispatcher中实现(typedef) typedef DerivedToFront<NoDuplicates<Colliders>::Result>::Result CL1; typedef CL1 CL2; template<class T,class U> struct Colliderable{enum{value=false};};//判断是否冲突 template<class T,class U> void CollideImpl(Base*,Base*);//冲突实现 template<> struct Colliderable<NullType,NullType>{enum{value=true};};//缺省Null推出一切 template<> void CollideImpl<NullType,NullType>(Base*,Base*) {throw std::runtime_error("Collide Not Impl.");}//缺省实现 template<> struct Colliderable<C,B>{enum{value=true};};//指示C,B的冲突 template<> void CollideImpl<C,B>(Base*,Base*)//C,B冲突实现 {std::cout<<"C,B"<<std::endl;} typedef void (*COLLIDE)(Base*, Base*); template<class T,class U,class R> struct CollideProvider; template<class T,class U> struct CollideProvider<T,U,COLLIDE> { COLLIDE operator()(){return CollideImpl<T,U>;} }; //定义用户的dispatcher并且填好表 typedef Dispatcher2<CL1,CL2,Colliderable,COLLIDE,CollideProvider> CollideDispatcher; CollideDispatcher collidedispather;//这里实际上也可以再封装,从而不需要再定义变量 class Base { public: virtual int ID1(){return CollideDispatcher::InnerID1<Base>::value;}; virtual int ID2(){return CollideDispatcher::InnerID2<Base>::value;}; }; class A:public Base { public: int ID1(){return CollideDispatcher::InnerID1<A>::value;}; int ID2(){return CollideDispatcher::InnerID2<A>::value;}; }; class B:public Base { public: int ID1(){return CollideDispatcher::InnerID1[b]::value;}; int ID2(){return CollideDispatcher::InnerID2[b]::value;}; }; class C:public Base { public: int ID1(){return CollideDispatcher::InnerID1<C>::value;}; int ID2(){return CollideDispatcher::InnerID2<C>::value;}; }; class D:public B { public: int ID1(){return CollideDispatcher::InnerID1<D>::value;}; int ID2(){return CollideDispatcher::InnerID2<D>::value;}; }; void Collide(Base* c1,Base* c2) { CollideDispatcher::GetDisp(c1->ID1(),c2->ID2())(c1,c2); } int main(void) { Base base;A a;B b;C c;D d; Base* p1=&c;Base* p2=&d;Base* p3=&a; try { Collide(p1,p2); Collide(p1,p3); } catch(std::runtime_error e) { std::cerr<<e.what(); } }
这里面的collide是非对称得。
TypeList可用Append。
那个dispatcher的静态量也可以不用声明(再把Dispatch2包一次)。
c1和c2碰撞,总是先遍历c2的继承层次。

欢迎大家批评指正。
上传的附件
文件类型: cpp doubledispatchtest.cpp (10.6 KB, 0 次查看)
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
回复

书签

主题工具
显示模式

发帖规则
不可以发表新主题
不可以发表回复
不可以上传附件
不可以编辑自己的帖子

启用 BB 代码
论坛启用 表情符号
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用



所有时间均为格林尼治时间 +9。现在的时间是 08:05 AM


Powered by vBulletin® 版本 3.7.0
版权所有 ©2000 - 2009,Jelsoft Enterprises Ltd.
(C) Copy Right All Right Reserved 2001 - 2007

Search Engine Friendly URLs by vBSEO 3.1.0