diff options
Diffstat (limited to 'shared/loki/MultiMethods.h')
-rw-r--r-- | shared/loki/MultiMethods.h | 586 |
1 files changed, 293 insertions, 293 deletions
diff --git a/shared/loki/MultiMethods.h b/shared/loki/MultiMethods.h index d095cfae..ece4fb17 100644 --- a/shared/loki/MultiMethods.h +++ b/shared/loki/MultiMethods.h @@ -2,14 +2,14 @@ // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: -// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// 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 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" +// 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_ @@ -36,210 +36,210 @@ namespace Loki // Helps implementing optional symmetry //////////////////////////////////////////////////////////////////////////////// - namespace Private +namespace Private +{ +template <class SomeLhs, class SomeRhs, + class Executor, typename ResultType> +struct InvocationTraits +{ + static ResultType + DoDispatch(SomeLhs& lhs, SomeRhs& rhs, + Executor& exec, Int2Type<false>) { - 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); - } - }; + 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 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>) { - 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()); + 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); } - - 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()); + 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()); } +}; - 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) +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) { - callbackMap_[KeyType(lhs, rhs)] = fun; + DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun); } - - template <class BaseLhs, class BaseRhs, - typename ResultType, typename CallbackType> - bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType> - ::DoRemove(TypeInfo lhs, TypeInfo rhs) + + template <class SomeLhs, class SomeRhs> + bool Remove() { - return callbackMap_.erase(KeyType(lhs, rhs)) == 1; + return DoRemove(typeid(SomeLhs), typeid(SomeRhs)); } - template <class BaseLhs, class BaseRhs, - typename ResultType, typename CallbackType> - ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType> - ::Go(BaseLhs& lhs, BaseRhs& rhs) + 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()) { - 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); + 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 +template <class To, class From> +struct StaticCaster +{ + static To& Cast(From& obj) { - static To& Cast(From& obj) - { - return static_cast<To&>(obj); - } - }; + return static_cast<To&>(obj); + } +}; //////////////////////////////////////////////////////////////////////////////// // class template DynamicCaster // Implementation of the CastingPolicy used by FunctorDispatcher //////////////////////////////////////////////////////////////////////////////// - template <class To, class From> - struct DynamicCaster +template <class To, class From> +struct DynamicCaster +{ + static To& Cast(From& obj) { - static To& Cast(From& obj) - { - return dynamic_cast<To&>(obj); - } - }; + return dynamic_cast<To&>(obj); + } +}; //////////////////////////////////////////////////////////////////////////////// // class template Private::FnDispatcherHelper // Implements trampolines and argument swapping used by FnDispatcher //////////////////////////////////////////////////////////////////////////////// - namespace Private +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) { - 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); - } - }; + return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); + } + static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs) + { + return Trampoline(lhs, rhs); } +}; +} //////////////////////////////////////////////////////////////////////////////// // class template FnDispatcher @@ -247,102 +247,102 @@ namespace Loki // 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 +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() { - 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 - { + 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() + BaseLhs, BaseRhs, + SomeLhs, SomeRhs, + ResultType, + CastingPolicy<SomeLhs,BaseLhs>, + CastingPolicy<SomeRhs,BaseRhs>, + callback> Local; + + Add<SomeLhs, SomeRhs>(&Local::Trampoline); + if (symmetric) { - backEnd_.template Remove<SomeLhs, SomeRhs>(); + Add<SomeRhs, SomeLhs>(&Local::TrampolineR); } + } - ResultType Go(BaseLhs& lhs, BaseRhs& rhs) - { - return backEnd_.Go(lhs, rhs); - } - }; + 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 +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>) { - 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>()); - } - }; + 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 @@ -350,63 +350,63 @@ namespace Loki // 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; +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_; + 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))); +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) - { + 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>(); + // 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))); } + } - ResultType Go(BaseLhs& lhs, BaseRhs& rhs) - { - return backEnd_.Go(lhs, rhs); - } - }; + 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 |