diff options
Diffstat (limited to 'shared/loki/MultiMethods.h')
-rw-r--r-- | shared/loki/MultiMethods.h | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/shared/loki/MultiMethods.h b/shared/loki/MultiMethods.h deleted file mode 100644 index ec5b7788..00000000 --- a/shared/loki/MultiMethods.h +++ /dev/null @@ -1,415 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// The Loki Library -// Copyright (c) 2001 by Andrei Alexandrescu -// This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design -// Patterns Applied". Copyright (c) 2001. Addison-Wesley. -// Permission to use, copy, modify, distribute and sell this software for any -// purpose is hereby granted without fee, provided that the above copyright -// notice appear in all copies and that both that copyright notice and this -// permission notice appear in supporting documentation. -// The author or Addison-Wesley Longman make no representations about the -// suitability of this software for any purpose. It is provided "as is" -// without express or implied warranty. -//////////////////////////////////////////////////////////////////////////////// -#ifndef LOKI_MULTIMETHODS_INC_ -#define LOKI_MULTIMETHODS_INC_ - -// $Id: MultiMethods.h 751 2006-10-17 19:50:37Z syntheticpp $ - - -#include "Typelist.h" -#include "LokiTypeInfo.h" -#include "Functor.h" -#include "AssocVector.h" - -//////////////////////////////////////////////////////////////////////////////// -// IMPORTANT NOTE: -// The double dispatchers implemented below differ from the excerpts shown in -// the book - they are simpler while respecting the same interface. -//////////////////////////////////////////////////////////////////////////////// - -namespace Loki -{ -//////////////////////////////////////////////////////////////////////////////// -// class template InvocationTraits (helper) -// Helps implementing optional symmetry -//////////////////////////////////////////////////////////////////////////////// - -namespace Private -{ -template < class SomeLhs, class SomeRhs, - class Executor, typename ResultType > -struct InvocationTraits -{ - static ResultType - DoDispatch(SomeLhs& lhs, SomeRhs& rhs, - Executor& exec, Int2Type<false>) - { - return exec.Fire(lhs, rhs); - } - static ResultType - DoDispatch(SomeLhs& lhs, SomeRhs& rhs, - Executor& exec, Int2Type<true>) - { - return exec.Fire(rhs, lhs); - } -}; -} - -//////////////////////////////////////////////////////////////////////////////// -// class template StaticDispatcher -// Implements an automatic static double dispatcher based on two typelists -//////////////////////////////////////////////////////////////////////////////// - -template -< -class Executor, - class BaseLhs, - class TypesLhs, - bool symmetric = true, - class BaseRhs = BaseLhs, - class TypesRhs = TypesLhs, - typename ResultType = void - > -class StaticDispatcher -{ - template <class SomeLhs> - static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, - Executor exec, NullType) - { return exec.OnError(lhs, rhs); } - - template <class Head, class Tail, class SomeLhs> - static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs, - Executor exec, Typelist<Head, Tail>) - { - if (Head* p2 = dynamic_cast<Head*>(&rhs)) - { - Int2Type < (symmetric && - int(TL::IndexOf<TypesRhs, Head>::value) < - int(TL::IndexOf<TypesLhs, SomeLhs>::value)) > i2t; - - typedef Private::InvocationTraits < - SomeLhs, Head, Executor, ResultType > CallTraits; - - return CallTraits::DoDispatch(lhs, *p2, exec, i2t); - } - return DispatchRhs(lhs, rhs, exec, Tail()); - } - - static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs, - Executor exec, NullType) - { return exec.OnError(lhs, rhs); } - - template <class Head, class Tail> - static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs, - Executor exec, Typelist<Head, Tail>) - { - if (Head* p1 = dynamic_cast<Head*>(&lhs)) - { - return DispatchRhs(*p1, rhs, exec, TypesRhs()); - } - return DispatchLhs(lhs, rhs, exec, Tail()); - } - -public: - static ResultType Go(BaseLhs& lhs, BaseRhs& rhs, - Executor exec) - { return DispatchLhs(lhs, rhs, exec, TypesLhs()); } -}; - -//////////////////////////////////////////////////////////////////////////////// -// class template BasicDispatcher -// Implements a logarithmic double dispatcher for functors (or functions) -// Doesn't offer automated casts or symmetry -//////////////////////////////////////////////////////////////////////////////// - -template -< -class BaseLhs, - class BaseRhs = BaseLhs, - typename ResultType = void, - typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&) - > -class BasicDispatcher -{ - typedef std::pair<TypeInfo, TypeInfo> KeyType; - typedef CallbackType MappedType; - typedef AssocVector<KeyType, MappedType> MapType; - MapType callbackMap_; - - void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun); - bool DoRemove(TypeInfo lhs, TypeInfo rhs); - -public: - template <class SomeLhs, class SomeRhs> - void Add(CallbackType fun) - { - DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun); - } - - template <class SomeLhs, class SomeRhs> - bool Remove() - { - return DoRemove(typeid(SomeLhs), typeid(SomeRhs)); - } - - ResultType Go(BaseLhs& lhs, BaseRhs& rhs); -}; - -// Non-inline to reduce compile time overhead... -template < class BaseLhs, class BaseRhs, - typename ResultType, typename CallbackType > -void BasicDispatcher<BaseLhs, BaseRhs, ResultType, CallbackType> -::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun) -{ - callbackMap_[KeyType(lhs, rhs)] = fun; -} - -template < class BaseLhs, class BaseRhs, - typename ResultType, typename CallbackType > -bool BasicDispatcher<BaseLhs, BaseRhs, ResultType, CallbackType> -::DoRemove(TypeInfo lhs, TypeInfo rhs) -{ - return callbackMap_.erase(KeyType(lhs, rhs)) == 1; -} - -template < class BaseLhs, class BaseRhs, - typename ResultType, typename CallbackType > -ResultType BasicDispatcher<BaseLhs, BaseRhs, ResultType, CallbackType> -::Go(BaseLhs& lhs, BaseRhs& rhs) -{ - typename MapType::key_type k(typeid(lhs), typeid(rhs)); - typename MapType::iterator i = callbackMap_.find(k); - if (i == callbackMap_.end()) - { - throw std::runtime_error("Function not found"); - } - return (i->second)(lhs, rhs); -} - -//////////////////////////////////////////////////////////////////////////////// -// class template StaticCaster -// Implementation of the CastingPolicy used by FunctorDispatcher -//////////////////////////////////////////////////////////////////////////////// - -template <class To, class From> -struct StaticCaster -{ - static To& Cast(From& obj) - { - return static_cast<To&>(obj); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// class template DynamicCaster -// Implementation of the CastingPolicy used by FunctorDispatcher -//////////////////////////////////////////////////////////////////////////////// - -template <class To, class From> -struct DynamicCaster -{ - static To& Cast(From& obj) - { - return dynamic_cast<To&>(obj); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// class template Private::FnDispatcherHelper -// Implements trampolines and argument swapping used by FnDispatcher -//////////////////////////////////////////////////////////////////////////////// - -namespace Private -{ -template < class BaseLhs, class BaseRhs, - class SomeLhs, class SomeRhs, - typename ResultType, - class CastLhs, class CastRhs, - ResultType (*Callback)(SomeLhs&, SomeRhs&) > -struct FnDispatcherHelper -{ - static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) - { - return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); - } - static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs) - { - return Trampoline(lhs, rhs); - } -}; -} - -//////////////////////////////////////////////////////////////////////////////// -// class template FnDispatcher -// Implements an automatic logarithmic double dispatcher for functions -// Features automated conversions -//////////////////////////////////////////////////////////////////////////////// - -template < class BaseLhs, class BaseRhs = BaseLhs, - typename ResultType = void, - template <class, class> class CastingPolicy = DynamicCaster, - template <class, class, class, class> - class DispatcherBackend = BasicDispatcher > -class FnDispatcher -{ - DispatcherBackend < BaseLhs, BaseRhs, ResultType, - ResultType (*)(BaseLhs&, BaseRhs&) > backEnd_; - -public: - template <class SomeLhs, class SomeRhs> - void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&)) - { - return backEnd_.template Add<SomeLhs, SomeRhs>(pFun); - } - - template < class SomeLhs, class SomeRhs, - ResultType (*callback)(SomeLhs&, SomeRhs&) > - void Add() - { - typedef Private::FnDispatcherHelper < - BaseLhs, BaseRhs, - SomeLhs, SomeRhs, - ResultType, - CastingPolicy<SomeLhs, BaseLhs>, - CastingPolicy<SomeRhs, BaseRhs>, - callback > Local; - - Add<SomeLhs, SomeRhs>(&Local::Trampoline); - } - - template < class SomeLhs, class SomeRhs, - ResultType (*callback)(SomeLhs&, SomeRhs&), - bool symmetric > - void Add(bool = true) // [gcc] dummy bool - { - typedef Private::FnDispatcherHelper < - BaseLhs, BaseRhs, - SomeLhs, SomeRhs, - ResultType, - CastingPolicy<SomeLhs, BaseLhs>, - CastingPolicy<SomeRhs, BaseRhs>, - callback > Local; - - Add<SomeLhs, SomeRhs>(&Local::Trampoline); - if (symmetric) - { - Add<SomeRhs, SomeLhs>(&Local::TrampolineR); - } - } - - template <class SomeLhs, class SomeRhs> - void Remove() - { - backEnd_.template Remove<SomeLhs, SomeRhs>(); - } - - ResultType Go(BaseLhs& lhs, BaseRhs& rhs) - { - return backEnd_.Go(lhs, rhs); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// class template FunctorDispatcherAdaptor -// permits use of FunctorDispatcher under gcc.2.95.2/3 -/////////////////////////////////////////////////////////////////////////////// - -namespace Private -{ -template < class BaseLhs, class BaseRhs, - class SomeLhs, class SomeRhs, - typename ResultType, - class CastLhs, class CastRhs, - class Fun, bool SwapArgs > -class FunctorDispatcherHelper -{ - Fun fun_; - ResultType Fire(BaseLhs& lhs, BaseRhs& rhs, Int2Type<false>) - { - return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); - } - ResultType Fire(BaseLhs& rhs, BaseRhs& lhs, Int2Type<true>) - { - return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); - } -public: - FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {} - - ResultType operator()(BaseLhs& lhs, BaseRhs& rhs) - { - return Fire(lhs, rhs, Int2Type<SwapArgs>()); - } -}; -} - -//////////////////////////////////////////////////////////////////////////////// -// class template FunctorDispatcher -// Implements a logarithmic double dispatcher for functors -// Features automated casting -//////////////////////////////////////////////////////////////////////////////// - -template < class BaseLhs, class BaseRhs = BaseLhs, - typename ResultType = void, - template <class, class> class CastingPolicy = DynamicCaster, - template <class, class, class, class> - class DispatcherBackend = BasicDispatcher > -class FunctorDispatcher -{ - typedef LOKI_TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList; - typedef Functor<ResultType, ArgsList, LOKI_DEFAULT_THREADING> FunctorType; - - DispatcherBackend<BaseLhs, BaseRhs, ResultType, FunctorType> backEnd_; - -public: - template <class SomeLhs, class SomeRhs, class Fun> - void Add(const Fun& fun) - { - typedef Private::FunctorDispatcherHelper < - BaseLhs, BaseRhs, - SomeLhs, SomeRhs, - ResultType, - CastingPolicy<SomeLhs, BaseLhs>, - CastingPolicy<SomeRhs, BaseRhs>, - Fun, false > Adapter; - - backEnd_.template Add<SomeLhs, SomeRhs>(FunctorType(Adapter(fun))); - } - template <class SomeLhs, class SomeRhs, bool symmetric, class Fun> - void Add(const Fun& fun) - { - Add<SomeLhs, SomeRhs>(fun); - - if (symmetric) - { - // Note: symmetry only makes sense where BaseLhs==BaseRhs - typedef Private::FunctorDispatcherHelper < - BaseLhs, BaseLhs, - SomeLhs, SomeRhs, - ResultType, - CastingPolicy<SomeLhs, BaseLhs>, - CastingPolicy<SomeRhs, BaseLhs>, - Fun, true > AdapterR; - - backEnd_.template Add<SomeRhs, SomeLhs>(FunctorType(AdapterR(fun))); - } - } - - template <class SomeLhs, class SomeRhs> - void Remove() - { - backEnd_.template Remove<SomeLhs, SomeRhs>(); - } - - ResultType Go(BaseLhs& lhs, BaseRhs& rhs) - { - return backEnd_.Go(lhs, rhs); - } -}; -} // namespace Loki - - - -#endif // end file guardian - |