added support for return type void

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@101 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
humesikkins 2003-02-27 15:51:56 +00:00
parent e4aac8f7af
commit ba50ac6da2

View file

@ -13,30 +13,29 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: Oct 28, 2002 // Last update: Feb 19, 2003
// Because MSVC 6.0 does not allow a functions with a return // All dispatchers now support void as return type.
// type of cv void to return an expression of type "cv void" (6.6.3), this //
// port currently *does not* support void as return type.
// //
// Because the VC 6.0 does not support explicit template argument specification // The port now uses Tye2Type-parameters instead of plain pointers as
// for member functions (14.8.1), I added dummy parameters to functions // a workaround of VC's explicit template argument specification bug.
// requiring this feature. //
// For example: // For example:
// The original declaration of BasicDispatcher::Add looks like this: // The original declaration of BasicDispatcher::Add looks like this:
// //
// template <class SomeLhs, class SomeRhs> // template <class SomeLhs, class SomeRhs>
// void Add(CallbackType fun); // void Add(CallbackType fun);
//
// and you call it like this: // and you call it like this:
// obj.Add<Type1, Type2>(yourFun); // obj.Add<Type1, Type2>(yourFun);
// //
// This port uses: // This port uses:
// //
// template <class SomeLhs, class SomeRhs> // template <class SomeLhs, class SomeRhs>
// void Add(CallbackType fun, SomeLhs* pDummy1, SomeRhs* pDummy2); // void Add(CallbackType fun, Type2Type<SomeLhs>, Type2Type<SomeRhs>);
// //
// and you call it like this: // and you call it like this:
// obj.Add(yourFun, (Type1*)0, (Type2*)0); // obj.Add(yourFun, Type2Type<Type1>(), Type2Type<Type2>());
#ifndef MULTIMETHODS_INC_ #ifndef MULTIMETHODS_INC_
@ -55,36 +54,153 @@
namespace Loki namespace Loki
{ {
////////////////////////////////////////////////////////////////////////////////
// class template InvocationTraits (helper)
// Helps implementing optional symmetry
////////////////////////////////////////////////////////////////////////////////
namespace Private ////////////////////////////////////////////////////////////////////////////////
// Implementation helpers for StaticDispatcher
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class SomeLhs, class SomeRhs,
class Executor, typename ResultType>
struct InvocationTraits
{ {
template <class SomeLhs, class SomeRhs, static ResultType
class Executor, typename ResultType> DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
struct InvocationTraits
{ {
static ResultType return exec.Fire(lhs, rhs);
DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>) }
{ static ResultType DoDispatch( SomeLhs& lhs, SomeRhs& rhs,
return exec.Fire(lhs, rhs); Executor& exec, Int2Type<true>)
} {
static ResultType DoDispatch( SomeLhs& lhs, SomeRhs& rhs, return exec.Fire(rhs, lhs);
Executor& exec, Int2Type<true>) }
{ };
return exec.Fire(rhs, lhs);
} template <class SomeLhs, class SomeRhs, class Executor>
}; struct InvocationTraitsVoid
} {
typedef void ResultType;
static ResultType
DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
{
exec.Fire(lhs, rhs);
}
static ResultType DoDispatch( SomeLhs& lhs, SomeRhs& rhs,
Executor& exec, Int2Type<true>)
{
exec.Fire(rhs, lhs);
}
};
// Implementation for StaticDispatcher with result type != void
template<class Executor, class BaseLhs, class TypesLhs, bool symmetric,
class BaseRhs, class TypesRhs, typename ResultType>
class StaticDispatcherBase
{
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()); }
};
// Implementation for StaticDispatcher with result type = void
template<class Executor, class BaseLhs, class TypesLhs, bool symmetric,
class BaseRhs, class TypesRhs>
class StaticDispatcherVoidBase
{
typedef void ResultType;
template <class SomeLhs>
static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs,
Executor exec, NullType)
{ 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::InvocationTraitsVoid<
SomeLhs, Head, Executor> CallTraits;
CallTraits::DoDispatch(lhs, *p2, exec, i2t);
return;
}
DispatchRhs(lhs, rhs, exec, Tail());
}
static ResultType DispatchLhs( BaseLhs& lhs, BaseRhs& rhs,
Executor exec, NullType)
{ 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))
{
DispatchRhs(*p1, rhs, exec, TypesRhs());
return;
}
DispatchLhs(lhs, rhs, exec, Tail());
}
public:
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
Executor exec)
{ DispatchLhs(lhs, rhs, exec, TypesLhs()); }
};
} // namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template StaticDispatcher // class template StaticDispatcher
// Implements an automatic static double dispatcher based on two typelists // Implements an automatic static double dispatcher based on two typelists
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template
template
< <
class Executor, class Executor,
class BaseLhs, class BaseLhs,
@ -92,123 +208,166 @@ namespace Loki
bool symmetric = true, bool symmetric = true,
class BaseRhs = BaseLhs, class BaseRhs = BaseLhs,
class TypesRhs = TypesLhs, class TypesRhs = TypesLhs,
typename ResultType = int/*void*/ typename ResultType = int
> >
class StaticDispatcher class StaticDispatcher : public ::Loki::Select
<
::Loki::Private::IsVoid<ResultType>::value,
::Loki::Private::StaticDispatcherVoidBase<Executor,
BaseLhs, TypesLhs, symmetric, BaseRhs,
TypesRhs>,
::Loki::Private::StaticDispatcherBase<Executor,
BaseLhs, TypesLhs, symmetric, BaseRhs,
TypesRhs, ResultType>
>::Result
{ {
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: public:
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs, // member functions moved to base class
Executor exec) // static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
{ return DispatchLhs(lhs, rhs, exec, TypesLhs()); } // Executor exec)
}; };
////////////////////////////////////////////////////////////////////////////////
// Implementation helpers for BasicDispatcher
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
// Implementation for result types != void
template <class BaseLhs, class BaseRhs, typename ResultType,
typename CallbackType> struct BasicDispatcherBase;
// Implementation for result type = 0
template <class BaseLhs, class BaseRhs,
typename CallbackType> struct BasicDispatcherVoidBase;
// Common (independent of the result type) code for BasicDispatcher
template<typename CallbackType>
class BasicDispatcherCommonBase
{
private:
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun);
bool DoRemove(TypeInfo lhs, TypeInfo rhs);
protected:
typedef std::pair<TypeInfo,TypeInfo> KeyType;
typedef CallbackType MappedType;
typedef AssocVector<KeyType, MappedType> MapType;
MapType callbackMap_;
public:
template <class SomeLhs, class SomeRhs>
void Add(CallbackType fun, ::Loki::Type2Type<SomeLhs>,
::Loki::Type2Type<SomeRhs>)
{
DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
}
template <class SomeLhs, class SomeRhs>
bool Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{
return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
}
};
// Non-inline to reduce compile time overhead...
template <typename CallbackType>
void BasicDispatcherCommonBase<CallbackType>
::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
{
callbackMap_[KeyType(lhs, rhs)] = fun;
}
template <typename CallbackType>
bool BasicDispatcherCommonBase<CallbackType>
::DoRemove(TypeInfo lhs, TypeInfo rhs)
{
return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
}
// Implementation for result types != void
template <class BaseLhs, class BaseRhs, typename ResultType,
typename CallbackType>
struct BasicDispatcherBase : public BasicDispatcherCommonBase<CallbackType>
{
typedef BasicDispatcherCommonBase<CallbackType> Base;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
};
template <class BaseLhs, class BaseRhs,
typename ResultType, typename CallbackType>
ResultType
BasicDispatcherBase<BaseLhs,BaseRhs,ResultType,CallbackType>
::Go(BaseLhs& lhs, BaseRhs& rhs)
{
typename MapType::key_type k(typeid(lhs),typeid(rhs));
typename MapType::iterator i = Base::callbackMap_.find(k);
if (i == Base::callbackMap_.end())
{
throw std::runtime_error("Function not found");
}
return (i->second)(lhs, rhs);
}
// Implementation for result types = void
template <class BaseLhs, class BaseRhs, typename CallbackType>
struct BasicDispatcherVoidBase : public BasicDispatcherCommonBase<CallbackType>
{
typedef void ResultType;
typedef BasicDispatcherCommonBase<CallbackType> Base;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
};
template <class BaseLhs, class BaseRhs, typename CallbackType>
typename BasicDispatcherVoidBase<BaseLhs,BaseRhs, CallbackType>::ResultType
BasicDispatcherVoidBase<BaseLhs,BaseRhs, CallbackType>
::Go(BaseLhs& lhs, BaseRhs& rhs)
{
typename MapType::key_type k(typeid(lhs),typeid(rhs));
typename MapType::iterator i = Base::callbackMap_.find(k);
if (i == Base::callbackMap_.end())
{
throw std::runtime_error("Function not found");
}
(i->second)(lhs, rhs);
}
} // namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template BasicDispatcher // class template BasicDispatcher
// Implements a logarithmic double dispatcher for functors (or functions) // Implements a logarithmic double dispatcher for functors (or functions)
// Doesn't offer automated casts or symmetry // Doesn't offer automated casts or symmetry
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template
template
< <
class BaseLhs, class BaseLhs,
class BaseRhs = BaseLhs, class BaseRhs = BaseLhs,
typename ResultType = int/*void*/, typename ResultType = int,
typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&) typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
> >
class BasicDispatcher class BasicDispatcher : public ::Loki::Select
<
::Loki::Private::IsVoid<ResultType>::value,
::Loki::Private::BasicDispatcherVoidBase<
BaseLhs, BaseRhs, CallbackType>,
::Loki::Private::BasicDispatcherBase<
BaseLhs, BaseRhs, ResultType, CallbackType>
>::Result
{ {
typedef std::pair<TypeInfo,TypeInfo> KeyType; public:
typedef CallbackType MappedType; // member functions moved to base class
typedef AssocVector<KeyType, MappedType> MapType; // template <class SomeLhs, class SomeRhs>
MapType callbackMap_; // void Add(CallbackType fun, ::Loki::Type2Type<SomeLhs>,
// ::Loki::Type2Type<SomeRhs>)
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun); //
bool DoRemove(TypeInfo lhs, TypeInfo rhs); // template <class SomeLhs, class SomeRhs>
// bool Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
public: //
template <class SomeLhs, class SomeRhs> // ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
void Add(CallbackType fun, SomeLhs* pDummy1, SomeRhs* pDummy2)
{
DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);
}
template <class SomeLhs, class SomeRhs>
bool Remove(SomeLhs pDummy1, SomeRhs pDummy2)
{
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);
}
struct BasicDispatcherWrapper struct BasicDispatcherWrapper
{ {
@ -249,7 +408,7 @@ namespace Loki
{ {
static To& Cast(From& obj) static To& Cast(From& obj)
{ {
return dynamic_cast<To&>(obj); return dynamic_cast<To&>(obj);
} }
}; };
struct DynamicCasterWrapper struct DynamicCasterWrapper
@ -265,26 +424,84 @@ namespace Loki
// class template Private::FnDispatcherHelper // class template Private::FnDispatcherHelper
// Implements trampolines and argument swapping used by FnDispatcher // Implements trampolines and argument swapping used by FnDispatcher
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Private
namespace Private
{ {
template template <typename ResultType, class BaseLhs, class BaseRhs,
class DispatcherBackend>
struct FnDispatcherBase
{
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
return backEnd_.Go(lhs, rhs);
}
};
template <class BaseLhs, class BaseRhs, class DispatcherBackend>
struct FnDispatcherVoidBase
{
typedef void ResultType;
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
backEnd_.Go(lhs, rhs);
}
};
template< class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
class CastLhs, class CastRhs,
void (*Callback)(SomeLhs&, SomeRhs&)>
struct FnDispatcherHelperVoidBase
{
typedef void ResultType;
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{
Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
{
Trampoline(lhs, rhs);
}
};
template<typename ResultType, class BaseLhs, class BaseRhs,
class SomeLhs, class SomeRhs, class CastLhs, class CastRhs,
ResultType (*Callback)(SomeLhs&, SomeRhs&)>
struct FnDispatcherHelperBase
{
typedef void ResultType;
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{
Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
{
Trampoline(lhs, rhs);
}
};
template
< <
class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs, class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
typename ResultType, class CastLhs, class CastRhs, typename ResultType, class CastLhs, class CastRhs,
ResultType (*Callback)(SomeLhs&, SomeRhs&) ResultType (*Callback)(SomeLhs&, SomeRhs&)
> >
struct FnDispatcherHelper struct FnDispatcherHelper : public ::Loki::Select
{ <
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) ::Loki::Private::IsVoid<ResultType>::value,
{ FnDispatcherHelperVoidBase<BaseLhs, BaseRhs,
return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); SomeLhs, SomeRhs, CastLhs, CastRhs,
} Callback>,
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs) FnDispatcherHelperBase<ResultType, BaseLhs, BaseRhs,
{ SomeLhs, SomeRhs, CastLhs, CastRhs,
return Trampoline(lhs, rhs); Callback>
} >::Result
}; {};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -297,21 +514,36 @@ namespace Loki
typename ResultType = int/*void*/, typename ResultType = int/*void*/,
class CastingPolicy = DynamicCasterWrapper, class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper> class DispatcherBackend = BasicDispatcherWrapper>
class FnDispatcher class FnDispatcher : public ::Loki::Select
<
::Loki::Private::IsVoid<ResultType>::value,
::Loki::Private::FnDispatcherVoidBase<BaseLhs,
BaseRhs, DispatcherBackend>,
::Loki::Private::FnDispatcherBase<ResultType, BaseLhs,
BaseRhs, DispatcherBackend>
>::Result
{ {
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType, typedef typename ::Loki::Select
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_; <::Loki::Private::IsVoid<ResultType>::value,
::Loki::Private::FnDispatcherVoidBase<BaseLhs,
BaseRhs, DispatcherBackend>,
::Loki::Private::FnDispatcherBase<ResultType, BaseLhs,
BaseRhs, DispatcherBackend>
>::Result Base;
public: public:
template <class SomeLhs, class SomeRhs> template <class SomeLhs, class SomeRhs>
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&), SomeLhs* pDummy1, SomeRhs* pDummy2) void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&),
::Loki::Type2Type<SomeLhs>,
::Loki::Type2Type<SomeRhs>)
{ {
return backEnd_.Add(pFun, pDummy1, pDummy2); Base::backEnd_.Add(pFun, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
} }
template <class SomeLhs, class SomeRhs, template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&)> ResultType (*callback)(SomeLhs&, SomeRhs&)>
void Add(SomeLhs* pDummy1, SomeRhs* pDummy2) void Add(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{ {
typedef Private::FnDispatcherHelper< typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs, BaseLhs, BaseRhs,
@ -321,12 +553,14 @@ namespace Loki
typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type, typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local; callback> Local;
Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0); Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
} }
template <class SomeLhs, class SomeRhs, template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&)> ResultType (*callback)(SomeLhs&, SomeRhs&)>
void Add(SomeLhs* pDummy1, SomeRhs* pDummy2, bool Symmetric) void Add(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>,
bool Symmetric)
{ {
typedef Private::FnDispatcherHelper< typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs, BaseLhs, BaseRhs,
@ -336,23 +570,25 @@ namespace Loki
typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type, typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local; callback> Local;
Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0); Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
if (Symmetric) if (Symmetric)
{ {
Add(&Local::Trampoline, (SomeLhs*)0, (SomeRhs*)0); Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
} }
} }
template <class SomeLhs, class SomeRhs> template <class SomeLhs, class SomeRhs>
void Remove(SomeLhs* pDummy1, SomeRhs* pDummy2) void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{ {
backEnd_.Remove(pDummy1, pDummy2); Base::backEnd_.Remove(::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
} }
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{ // moved to base class
return backEnd_.Go(lhs, rhs); // ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
}
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -362,11 +598,8 @@ namespace Loki
namespace Private namespace Private
{ {
template <class BaseLhs, class BaseRhs, template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
class SomeLhs, class SomeRhs, typename ResultType, class CastLhs, class CastRhs, class Fun, bool SwapArgs>
typename ResultType,
class CastLhs, class CastRhs,
class Fun, bool SwapArgs>
class FunctorDispatcherHelper class FunctorDispatcherHelper
{ {
Fun fun_; Fun fun_;
@ -386,6 +619,76 @@ namespace Loki
return Fire(lhs,rhs,Int2Type<SwapArgs>()); return Fire(lhs,rhs,Int2Type<SwapArgs>());
} }
}; };
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
class CastLhs, class CastRhs, class Fun, bool SwapArgs>
class FunctorDispatcherHelperVoid
{
Fun fun_;
typedef void ResultType;
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
{
fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
{
fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
public:
FunctorDispatcherHelperVoid(const Fun& fun) : fun_(fun) {}
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
{
Fire(lhs,rhs,Int2Type<SwapArgs>());
}
};
template <class BaseLhs, class BaseRhs, typename ResultType,
class DispatcherBackend>
class FunctorDispatcherCommonBase
{
protected:
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType;
ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType,
FunctorType>::type backEnd_;
};
template <typename ResultType, class BaseLhs, class BaseRhs,
class DispatcherBackend>
class FunctorDispatcherBase : public FunctorDispatcherCommonBase<BaseLhs,
BaseRhs, ResultType, DispatcherBackend>
{
typedef FunctorDispatcherCommonBase<BaseLhs, BaseRhs, ResultType,
DispatcherBackend> Base;
public:
typedef typename Base::ArgsList ArgsList;
typedef typename Base::FunctorType FunctorType;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
return Base::backEnd_.Go(lhs, rhs);
}
};
template <class BaseLhs, class BaseRhs, class DispatcherBackend>
class FunctorDispatcherVoidBase : public FunctorDispatcherCommonBase<BaseLhs,
BaseRhs, void, DispatcherBackend>
{
typedef void ResultType;
typedef FunctorDispatcherCommonBase<BaseLhs, BaseRhs, ResultType,
DispatcherBackend> Base;
public:
typedef typename Base::ArgsList ArgsList;
typedef typename Base::FunctorType FunctorType;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
Base::backEnd_.Go(lhs, rhs);
}
};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -398,61 +701,74 @@ namespace Loki
typename ResultType = int/*void*/, typename ResultType = int/*void*/,
class CastingPolicy = DynamicCasterWrapper, class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper> class DispatcherBackend = BasicDispatcherWrapper>
class FunctorDispatcher class FunctorDispatcher : public ::Loki::Select
<
::Loki::Private::IsVoid<ResultType>::value,
::Loki::Private::FunctorDispatcherVoidBase<BaseLhs,
BaseRhs, DispatcherBackend>,
::Loki::Private::FunctorDispatcherBase<ResultType,
BaseLhs, BaseRhs, DispatcherBackend>
>::Result
{ {
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList; typedef typename ::Loki::Select
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType; <
::Loki::Private::IsVoid<ResultType>::value,
ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType, FunctorType>::type backEnd_; ::Loki::Private::FunctorDispatcherVoidBase<BaseLhs, BaseRhs,
DispatcherBackend>,
::Loki::Private::FunctorDispatcherBase<ResultType, BaseLhs, BaseRhs,
DispatcherBackend>
>::Result Base;
public: public:
template <class SomeLhs, class SomeRhs, class Fun> typedef Base::ArgsList ArgsList;
void Add(const Fun& fun, SomeLhs* pDummy1, SomeRhs* pDummy2) typedef Base::FunctorType FunctorType;
template <class SomeLhs, class SomeRhs, class Fun>
void Add(const Fun& fun, ::Loki::Type2Type<SomeLhs>,
::Loki::Type2Type<SomeRhs>)
{ {
typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne; typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseRhs>::type CastTwo; typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseRhs>::type CastTwo;
typedef Private::FunctorDispatcherHelper< typedef typename Select<
BaseLhs, BaseRhs, Private::IsVoid<ResultType>::value,
SomeLhs, SomeRhs, Private::FunctorDispatcherHelperVoid<BaseLhs, BaseRhs, SomeLhs,
ResultType, SomeRhs, CastOne,CastTwo,Fun, false>,
CastOne, Private::FunctorDispatcherHelper<BaseLhs, BaseRhs, SomeLhs, SomeRhs,
CastTwo, ResultType,CastOne,CastTwo,Fun, false>
Fun, false> Adapter; >::Result Adapter;
Base::backEnd_.Add(FunctorType(Adapter(fun), Loki::Disambiguate()),
Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
}
backEnd_.Add(FunctorType(Adapter(fun), (int*) 0), pDummy1, pDummy2);
}
template <class SomeLhs, class SomeRhs, class Fun> template <class SomeLhs, class SomeRhs, class Fun>
void Add(const Fun& fun, SomeLhs* pDummy1, SomeRhs* pDummy2, bool symmetric) void Add(const Fun& fun, ::Loki::Type2Type<SomeLhs>,
::Loki::Type2Type<SomeRhs>, bool symmetric)
{ {
Add(fun, pDummy1, pDummy2); Add(fun, Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
if (symmetric) if (symmetric)
{ {
// Note: symmetry only makes sense where BaseLhs==BaseRhs // Note: symmetry only makes sense where BaseLhs==BaseRhs
typedef Private::FunctorDispatcherHelper< typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
BaseLhs, BaseLhs, typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type CastTwo;
SomeLhs, SomeRhs, typedef typename Select<Private::IsVoid<ResultType>::value,
ResultType, Private::FunctorDispatcherHelperVoid<BaseLhs, BaseLhs,
ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type, SomeLhs, SomeRhs, CastOne,CastTwo, Fun, true>,
ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type, Private::FunctorDispatcherHelper<BaseLhs, BaseLhs,
Fun, true> AdapterR; ResultType, SomeLhs, SomeRhs,CastOne, CastTwo,Fun, true>
>::Result AdapterR;
backEnd_.Add(FunctorType(Adapter(fun)), pDummy1, pDummy2); Base::backEnd_.Add(FunctorType(Adapter(fun)),
} Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
}
} }
template <class SomeLhs, class SomeRhs> template <class SomeLhs, class SomeRhs>
void Remove(SomeLhs* pDummy1, SomeRhs* pDummy2) void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{ {
backEnd_.Remove(pDummy1, pDummy2); Base::backEnd_.Remove(Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
} }
ResultType Go(BaseLhs& lhs, BaseRhs& rhs) // moved to base class
{ // ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
return backEnd_.Go(lhs, rhs);
}
}; };
} // namespace Loki } // namespace Loki
@ -461,6 +777,8 @@ namespace Loki
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
// May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) // May 10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466)
// Oct 28, 2002: ported by Benjamin Kaufmann // Oct 28, 2002: ported by Benjamin Kaufmann
// Feb 19, 2003: replaced pointer-Dummies with Type2Type-Parameters and added
// support for return type void.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif #endif