00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef SOFA_HELPER_FNDISPATCHER_H
00028 #define SOFA_HELPER_FNDISPATCHER_H
00029
00030 #include <map>
00031 #include <typeinfo>
00032
00033 namespace sofa
00034 {
00035
00036 namespace helper
00037 {
00038
00039 class TypeInfo
00040 {
00041 public:
00042 const std::type_info* pt;
00043 TypeInfo(const std::type_info& t) : pt(&t) { }
00044 operator const std::type_info&() const { return *pt; }
00045 bool operator==(const TypeInfo& t) const { return *pt == *t.pt; }
00046 bool operator!=(const TypeInfo& t) const { return *pt != *t.pt; }
00047 #ifdef _MSC_VER
00048 bool operator<(const TypeInfo& t) const { return (pt->before(*t.pt)!=0); }
00049 #else
00050 bool operator<(const TypeInfo& t) const { return pt->before(*t.pt); }
00051 #endif
00052 };
00053
00054 template <class BaseClass, typename ResulT = void>
00055 class BasicDispatcher
00056 {
00057 public:
00058 typedef ResulT (*F)(BaseClass &,BaseClass &);
00059
00060 protected:
00061 typedef std::pair<TypeInfo,TypeInfo> KeyType;
00062 typedef std::map<KeyType, F> MapType;
00063 MapType callBackMap;
00064 virtual ~BasicDispatcher(){}
00065 public:
00066 void add(const std::type_info& class1, const std::type_info& class2, F fun)
00067 {
00068 callBackMap[KeyType(class1,class2)] = fun;
00069 }
00070
00071 void ignore(const std::type_info& class1, const std::type_info& class2)
00072 {
00073 callBackMap[KeyType(class1,class2)] = ignoreFn;
00074 }
00075
00076 template <class ConcreteClass1,class ConcreteClass2,ResulT (*F)(ConcreteClass1&,ConcreteClass2&), bool symetric>
00077 void ignore()
00078 {
00079 this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass1), typeid(ConcreteClass2), &ignoreFn);
00080 if (symetric)
00081 {
00082 this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass2), typeid(ConcreteClass1), &ignoreFn);
00083 }
00084 }
00085
00086 virtual ResulT defaultFn(BaseClass& arg1, BaseClass& arg2);
00087 static ResulT ignoreFn(BaseClass& arg1, BaseClass& arg2);
00088 ResulT go(BaseClass &arg1,BaseClass &arg2);
00090 bool isSupported(BaseClass &arg1, BaseClass &arg2);
00091 };
00092
00093 template <class BaseClass, typename ResulT>
00094 class FnDispatcher : public BasicDispatcher<BaseClass, ResulT>
00095 {
00096 public:
00097
00098 template <class ConcreteClass1, class ConcreteClass2,ResulT (*F)(ConcreteClass1&,ConcreteClass2&), bool symetric>
00099 void add()
00100 {
00101 struct Local
00102 {
00103 static ResulT trampoline(BaseClass &arg1,BaseClass &arg2)
00104 {
00105 return F(static_cast<ConcreteClass1 &> (arg1),
00106 static_cast<ConcreteClass2 &> (arg2));
00107 }
00108 static ResulT trampolineR(BaseClass &arg1,BaseClass &arg2)
00109 {
00110 return trampoline (arg2, arg1);
00111 }
00112 };
00113 this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass1), typeid(ConcreteClass2), &Local::trampoline);
00114 if (symetric)
00115 {
00116 this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass2), typeid(ConcreteClass1), &Local::trampolineR);
00117 }
00118 }
00119
00120 template <class ConcreteClass1, class ConcreteClass2, bool symetric>
00121 void ignore()
00122 {
00123 this->BasicDispatcher<BaseClass, ResulT>::ignore(typeid(ConcreteClass1), typeid(ConcreteClass2));
00124 if (symetric)
00125 {
00126 this->BasicDispatcher<BaseClass, ResulT>::ignore(typeid(ConcreteClass2), typeid(ConcreteClass1));
00127 }
00128 }
00129 };
00130
00131
00132 template <class BaseClass, typename ResulT>
00133 class SingletonFnDispatcher : public FnDispatcher<BaseClass, ResulT>
00134 {
00135 protected:
00136 SingletonFnDispatcher();
00137 public:
00138 static SingletonFnDispatcher<BaseClass, ResulT>* getInstance();
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 };
00158
00159 }
00160
00161 }
00162
00163 #endif