00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015 #ifndef LOKI_MULTIMETHODS_INC_
00016 #define LOKI_MULTIMETHODS_INC_
00017
00018
00019
00020
00021 #include "Typelist.h"
00022 #include "LokiTypeInfo.h"
00023 #include "Functor.h"
00024 #include "AssocVector.h"
00025
00027
00028
00029
00031
00032 namespace Loki
00033 {
00035
00036
00038
00039 namespace Private
00040 {
00041 template <class SomeLhs, class SomeRhs,
00042 class Executor, typename ResultType>
00043 struct InvocationTraits
00044 {
00045 static ResultType
00046 DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
00047 Executor& exec, Int2Type<false>)
00048 {
00049 return exec.Fire(lhs, rhs);
00050 }
00051 static ResultType
00052 DoDispatch(SomeLhs& lhs, SomeRhs& rhs,
00053 Executor& exec, Int2Type<true>)
00054 {
00055 return exec.Fire(rhs, lhs);
00056 }
00057 };
00058 }
00059
00061
00062
00064
00065 template
00066 <
00067 class Executor,
00068 class BaseLhs,
00069 class TypesLhs,
00070 bool symmetric = true,
00071 class BaseRhs = BaseLhs,
00072 class TypesRhs = TypesLhs,
00073 typename ResultType = void
00074 >
00075 class StaticDispatcher
00076 {
00077 template <class SomeLhs>
00078 static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
00079 Executor exec, NullType)
00080 { return exec.OnError(lhs, rhs); }
00081
00082 template <class Head, class Tail, class SomeLhs>
00083 static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,
00084 Executor exec, Typelist<Head, Tail>)
00085 {
00086 if (Head* p2 = dynamic_cast<Head*>(&rhs))
00087 {
00088 Int2Type<(symmetric &&
00089 int(TL::IndexOf<TypesRhs, Head>::value) <
00090 int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t;
00091
00092 typedef Private::InvocationTraits<
00093 SomeLhs, Head, Executor, ResultType> CallTraits;
00094
00095 return CallTraits::DoDispatch(lhs, *p2, exec, i2t);
00096 }
00097 return DispatchRhs(lhs, rhs, exec, Tail());
00098 }
00099
00100 static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
00101 Executor exec, NullType)
00102 { return exec.OnError(lhs, rhs); }
00103
00104 template <class Head, class Tail>
00105 static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,
00106 Executor exec, Typelist<Head, Tail>)
00107 {
00108 if (Head* p1 = dynamic_cast<Head*>(&lhs))
00109 {
00110 return DispatchRhs(*p1, rhs, exec, TypesRhs());
00111 }
00112 return DispatchLhs(lhs, rhs, exec, Tail());
00113 }
00114
00115 public:
00116 static ResultType Go(BaseLhs& lhs, BaseRhs& rhs,
00117 Executor exec)
00118 { return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
00119 };
00120
00122
00123
00124
00126
00127 template
00128 <
00129 class BaseLhs,
00130 class BaseRhs = BaseLhs,
00131 typename ResultType = void,
00132 typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
00133 >
00134 class BasicDispatcher
00135 {
00136 typedef std::pair<TypeInfo,TypeInfo> KeyType;
00137 typedef CallbackType MappedType;
00138 typedef AssocVector<KeyType, MappedType> MapType;
00139 MapType callbackMap_;
00140
00141 void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun);
00142 bool DoRemove(TypeInfo lhs, TypeInfo rhs);
00143
00144 public:
00145 template <class SomeLhs, class SomeRhs>
00146 void Add(CallbackType fun)
00147 {
00148 DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
00149 }
00150
00151 template <class SomeLhs, class SomeRhs>
00152 bool Remove()
00153 {
00154 return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
00155 }
00156
00157 ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
00158 };
00159
00160
00161 template <class BaseLhs, class BaseRhs,
00162 typename ResultType, typename CallbackType>
00163 void BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
00164 ::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
00165 {
00166 callbackMap_[KeyType(lhs, rhs)] = fun;
00167 }
00168
00169 template <class BaseLhs, class BaseRhs,
00170 typename ResultType, typename CallbackType>
00171 bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
00172 ::DoRemove(TypeInfo lhs, TypeInfo rhs)
00173 {
00174 return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
00175 }
00176
00177 template <class BaseLhs, class BaseRhs,
00178 typename ResultType, typename CallbackType>
00179 ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>
00180 ::Go(BaseLhs& lhs, BaseRhs& rhs)
00181 {
00182 typename MapType::key_type k(typeid(lhs),typeid(rhs));
00183 typename MapType::iterator i = callbackMap_.find(k);
00184 if (i == callbackMap_.end())
00185 {
00186 throw std::runtime_error("Function not found");
00187 }
00188 return (i->second)(lhs, rhs);
00189 }
00190
00192
00193
00195
00196 template <class To, class From>
00197 struct StaticCaster
00198 {
00199 static To& Cast(From& obj)
00200 {
00201 return static_cast<To&>(obj);
00202 }
00203 };
00204
00206
00207
00209
00210 template <class To, class From>
00211 struct DynamicCaster
00212 {
00213 static To& Cast(From& obj)
00214 {
00215 return dynamic_cast<To&>(obj);
00216 }
00217 };
00218
00220
00221
00223
00224 namespace Private
00225 {
00226 template <class BaseLhs, class BaseRhs,
00227 class SomeLhs, class SomeRhs,
00228 typename ResultType,
00229 class CastLhs, class CastRhs,
00230 ResultType (*Callback)(SomeLhs&, SomeRhs&)>
00231 struct FnDispatcherHelper
00232 {
00233 static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
00234 {
00235 return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
00236 }
00237 static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
00238 {
00239 return Trampoline(lhs, rhs);
00240 }
00241 };
00242 }
00243
00245
00246
00247
00249
00250 template <class BaseLhs, class BaseRhs = BaseLhs,
00251 typename ResultType = void,
00252 template <class, class> class CastingPolicy = DynamicCaster,
00253 template <class, class, class, class>
00254 class DispatcherBackend = BasicDispatcher>
00255 class FnDispatcher
00256 {
00257 DispatcherBackend<BaseLhs, BaseRhs, ResultType,
00258 ResultType (*)(BaseLhs&, BaseRhs&)> backEnd_;
00259
00260 public:
00261 template <class SomeLhs, class SomeRhs>
00262 void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&))
00263 {
00264 return backEnd_.template Add<SomeLhs, SomeRhs>(pFun);
00265 }
00266
00267 template <class SomeLhs, class SomeRhs,
00268 ResultType (*callback)(SomeLhs&, SomeRhs&)>
00269 void Add()
00270 {
00271 typedef Private::FnDispatcherHelper<
00272 BaseLhs, BaseRhs,
00273 SomeLhs, SomeRhs,
00274 ResultType,
00275 CastingPolicy<SomeLhs,BaseLhs>,
00276 CastingPolicy<SomeRhs,BaseRhs>,
00277 callback> Local;
00278
00279 Add<SomeLhs, SomeRhs>(&Local::Trampoline);
00280 }
00281
00282 template <class SomeLhs, class SomeRhs,
00283 ResultType (*callback)(SomeLhs&, SomeRhs&),
00284 bool symmetric>
00285 void Add(bool = true)
00286 {
00287 typedef Private::FnDispatcherHelper<
00288 BaseLhs, BaseRhs,
00289 SomeLhs, SomeRhs,
00290 ResultType,
00291 CastingPolicy<SomeLhs,BaseLhs>,
00292 CastingPolicy<SomeRhs,BaseRhs>,
00293 callback> Local;
00294
00295 Add<SomeLhs, SomeRhs>(&Local::Trampoline);
00296 if (symmetric)
00297 {
00298 Add<SomeRhs, SomeLhs>(&Local::TrampolineR);
00299 }
00300 }
00301
00302 template <class SomeLhs, class SomeRhs>
00303 void Remove()
00304 {
00305 backEnd_.template Remove<SomeLhs, SomeRhs>();
00306 }
00307
00308 ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
00309 {
00310 return backEnd_.Go(lhs, rhs);
00311 }
00312 };
00313
00315
00316
00318
00319 namespace Private
00320 {
00321 template <class BaseLhs, class BaseRhs,
00322 class SomeLhs, class SomeRhs,
00323 typename ResultType,
00324 class CastLhs, class CastRhs,
00325 class Fun, bool SwapArgs>
00326 class FunctorDispatcherHelper
00327 {
00328 Fun fun_;
00329 ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
00330 {
00331 return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
00332 }
00333 ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
00334 {
00335 return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
00336 }
00337 public:
00338 FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {}
00339
00340 ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
00341 {
00342 return Fire(lhs,rhs,Int2Type<SwapArgs>());
00343 }
00344 };
00345 }
00346
00348
00349
00350
00352
00353 template <class BaseLhs, class BaseRhs = BaseLhs,
00354 typename ResultType = void,
00355 template <class, class> class CastingPolicy = DynamicCaster,
00356 template <class, class, class, class>
00357 class DispatcherBackend = BasicDispatcher>
00358 class FunctorDispatcher
00359 {
00360 typedef LOKI_TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
00361 typedef Functor<ResultType, ArgsList, LOKI_DEFAULT_THREADING> FunctorType;
00362
00363 DispatcherBackend<BaseLhs, BaseRhs, ResultType, FunctorType> backEnd_;
00364
00365 public:
00366 template <class SomeLhs, class SomeRhs, class Fun>
00367 void Add(const Fun& fun)
00368 {
00369 typedef Private::FunctorDispatcherHelper<
00370 BaseLhs, BaseRhs,
00371 SomeLhs, SomeRhs,
00372 ResultType,
00373 CastingPolicy<SomeLhs, BaseLhs>,
00374 CastingPolicy<SomeRhs, BaseRhs>,
00375 Fun, false> Adapter;
00376
00377 backEnd_.template Add<SomeLhs, SomeRhs>(FunctorType(Adapter(fun)));
00378 }
00379 template <class SomeLhs, class SomeRhs, bool symmetric, class Fun>
00380 void Add(const Fun& fun)
00381 {
00382 Add<SomeLhs,SomeRhs>(fun);
00383
00384 if (symmetric)
00385 {
00386
00387 typedef Private::FunctorDispatcherHelper<
00388 BaseLhs, BaseLhs,
00389 SomeLhs, SomeRhs,
00390 ResultType,
00391 CastingPolicy<SomeLhs, BaseLhs>,
00392 CastingPolicy<SomeRhs, BaseLhs>,
00393 Fun, true> AdapterR;
00394
00395 backEnd_.template Add<SomeRhs, SomeLhs>(FunctorType(AdapterR(fun)));
00396 }
00397 }
00398
00399 template <class SomeLhs, class SomeRhs>
00400 void Remove()
00401 {
00402 backEnd_.template Remove<SomeLhs, SomeRhs>();
00403 }
00404
00405 ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
00406 {
00407 return backEnd_.Go(lhs, rhs);
00408 }
00409 };
00410 }
00411
00412
00413
00414 #endif // end file guardian
00415