Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members

DoubleDispatch.h

00001 // Copyright (C) 1999 Jean-Marc Valin
00002 
00003 #ifndef DOUBLE_DISPATCH_H
00004 #define DOUBLE_DISPATCH_H
00005 
00006 #include "typemap.h"
00007 #include "ObjectRef.h"
00008 #include "BaseException.h"
00009 
00010 //#ifdef NO_HASH_MAP
00011 #include <map>
00012 //#else
00013 //#include <hash_map>
00014 //#endif
00015 
00016 namespace FD {
00017 
00018 class DoubleDispatch;
00019 
00020 class DoubleDispatchException : public BaseException {
00021   protected:
00022    DoubleDispatch *table;
00023    std::string type1, type2;
00024   public:
00025    DoubleDispatchException(DoubleDispatch *_table, std::string _type1, std::string _type2);
00026    virtual void print(std::ostream &out = std::cerr);
00027    
00028 };
00029 
00030 //template<class T, class U>
00031 class DoubleDispatch {
00032   public:
00033    typedef ObjectRef (*funct_ptr) (ObjectRef x, ObjectRef y);
00034 
00035   protected:
00036    std::string name;
00037 //#ifdef NO_HASH_MAP
00038    //typedef map<const type_info *, funct_ptr> vtable1Type;
00039    //typedef map<const type_info *, vtable1Type > vtable2Type;
00040 
00041    typedef TypeMap<funct_ptr> vtable1Type;
00042    typedef TypeMap<vtable1Type> vtable2Type;
00043 //#else
00044 //   typedef hash_map<const type_info *, funct_ptr> vtable1Type;
00045 //   typedef hash_map<const type_info *, vtable1Type > vtable2Type;
00046 //#endif
00047    vtable2Type vtable;
00048 
00049   public:
00050    DoubleDispatch(std::string _name) : name(_name) {}
00051 
00052    const std::string &getName() {return name;}
00053 
00054    void registerFunct(funct_ptr ptr, const std::type_info *x, const std::type_info *y)
00055    {
00056       vtable[x][y] = ptr;
00057    }
00058 
00059    ObjectRef call(ObjectRef x, ObjectRef y)
00060    {
00061       const std::type_info *t1 = &typeid(*x);
00062       const std::type_info *t2 = &typeid(*y);
00063       vtable2Type::iterator v1 = vtable.find(t1);
00064       if (v1!=vtable.end())
00065       {
00066          vtable1Type::iterator v2 = v1->second.find(t2);
00067          if (v2!=v1->second.end())
00068          {
00069             return v2->second(x,y);
00070          } else {
00071             throw new DoubleDispatchException(this, t1->name(), t2->name());
00072          }
00073       } else {
00074          throw new DoubleDispatchException(this, t1->name(), t2->name());
00075       }
00076    }
00077 };
00078 
00079 
00080 #define DEFINE_DOUBLE_VTABLE(klass) class klass {                                   \
00081   public:                                                                           \
00082    static DoubleDispatch &vtable() {static DoubleDispatch table(# klass); return table;}     \
00083    static ObjectRef perform(ObjectRef x, ObjectRef y)                               \
00084    {                                                                                \
00085       return vtable().call(x,y);                                                    \
00086    }                                                                                \
00087    static int reg(DoubleDispatch::funct_ptr ptr, const std::type_info *x, const std::type_info *y) \
00088    {                                                                                \
00089       vtable().registerFunct(ptr,x,y);                                              \
00090       return 0;                                                                     \
00091    }                                                                                \
00092 };
00093 
00094 #define REGISTER_DOUBLE_VTABLE(klass, func, type1, type2) \
00095         int dummy_vtable_init_for ## klass ## _ ## func =\
00096         klass::reg(func, &typeid(type1), &typeid(type2));
00097 
00098 
00099 #define REGISTER_DOUBLE_VTABLE_TEMPLATE(klass, func, type1, type2, type3, id) \
00100         int dummy_vtable_init_for ## klass ## func ## _ ## id =\
00101           klass::reg(func<type1,type2,type3>, &typeid(type1), &typeid(type2));
00102 
00103 }//namespace FD
00104 #endif

Generated on Wed Oct 5 14:28:55 2005 for FlowDesigner by  doxygen 1.4.4