fixed bugs in FnDispatcher::Add and FunctorDispatcher::Add

git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@123 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
humesikkins 2003-03-20 21:47:49 +00:00
parent 273dc0d85e
commit 4d8052faa7

View file

@ -13,7 +13,24 @@
// without express or implied warranty. // without express or implied warranty.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Last update: Mar 06, 2003 // Last update: Mar 20, 2003
// Interface change for FnDispatcher::Add:
// The trampoline-Version of FnDispatcher::Add needs explicit template
// argument specification for type and non-type parameters. Unfortunately
// all workarounds used so far failed for this member-function.
// Therefore I need to use a new one which leads to another interface change:
// Example (see "Modern C++ Design" Section 11.6)
// ----------------------------------------------
// Using the original one writes:
// typedef FnDispatcher<Shape> Dispatcher;
// void Hatch(Rectangle& lhs, Poly& rhs) {...}
//
// Dispatcher dis;
// disp.Add<Rectangle, Poly, &Hatch>();
//
// Using this port the example becomes:
// Dispatcher::AddI<Rectangle, Poly, &Hatch>()(dis);
//
// All dispatchers now have void as default value for return types. // All dispatchers now have void as default value for return types.
// All dispatchers now support void as return type. // All dispatchers now support void as return type.
// //
@ -62,9 +79,12 @@ namespace Loki
namespace Private namespace Private
{ {
template <class SomeLhs, class SomeRhs, template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>
class Executor, typename ResultType> struct InvocationTraitsBase
struct InvocationTraits {
protected:
template <class R>
struct BaseImpl
{ {
static ResultType static ResultType
DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>) DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
@ -77,11 +97,9 @@ namespace Private
return exec.Fire(rhs, lhs); return exec.Fire(rhs, lhs);
} }
}; };
template <>
template <class SomeLhs, class SomeRhs, class Executor> struct BaseImpl<void>
struct InvocationTraitsVoid
{ {
typedef void ResultType;
static ResultType static ResultType
DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>) DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
{ {
@ -93,11 +111,24 @@ namespace Private
exec.Fire(rhs, lhs); exec.Fire(rhs, lhs);
} }
}; };
public:
typedef BaseImpl<ResultType> Base;
};
template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>
struct InvocationTraits : public InvocationTraitsBase
<SomeLhs, SomeRhs, Executor, ResultType>::Base
{
};
// Implementation for StaticDispatcher with result type != void
template<class Executor, class BaseLhs, class TypesLhs, bool symmetric, template<class Executor, class BaseLhs, class TypesLhs, bool symmetric,
class BaseRhs, class TypesRhs, typename ResultType> class BaseRhs, class TypesRhs, typename ResultType>
class StaticDispatcherBase class StaticDispatcherBase
{
private:
// Base for ResultType != void
template <class R>
class In
{ {
template <class SomeLhs> template <class SomeLhs>
static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs, static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs,
@ -138,19 +169,17 @@ namespace Private
} }
protected: protected:
~StaticDispatcherBase() {} ~In() {}
public: public:
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs, static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
Executor exec) Executor exec)
{ return DispatchLhs(lhs, rhs, exec, TypesLhs()); } { return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
}; }; // In<R>
// Implementation for StaticDispatcher with result type = void // Base for ResultType == void
template<class Executor, class BaseLhs, class TypesLhs, bool symmetric, template <>
class BaseRhs, class TypesRhs> class In<void>
class StaticDispatcherVoidBase
{ {
typedef void ResultType;
template <class SomeLhs> template <class SomeLhs>
static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs, static ResultType DispatchRhs( SomeLhs& lhs, BaseRhs& rhs,
Executor exec, NullType) Executor exec, NullType)
@ -166,8 +195,8 @@ namespace Private
int(TL::IndexOf<TypesRhs, Head>::value) < int(TL::IndexOf<TypesRhs, Head>::value) <
int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t; int(TL::IndexOf<TypesLhs, SomeLhs>::value))> i2t;
typedef Private::InvocationTraitsVoid< typedef Private::InvocationTraits<
SomeLhs, Head, Executor> CallTraits; SomeLhs, Head, Executor, void> CallTraits;
CallTraits::DoDispatch(lhs, *p2, exec, i2t); CallTraits::DoDispatch(lhs, *p2, exec, i2t);
return; return;
@ -192,12 +221,15 @@ namespace Private
} }
protected: protected:
~StaticDispatcherVoidBase() {} ~In<void>() {}
public: public:
static ResultType Go( BaseLhs& lhs, BaseRhs& rhs, static ResultType Go( BaseLhs& lhs, BaseRhs& rhs,
Executor exec) Executor exec)
{ DispatchLhs(lhs, rhs, exec, TypesLhs()); } { DispatchLhs(lhs, rhs, exec, TypesLhs()); }
}; }; // In<void>
public:
typedef In<ResultType> Base;
}; // StaticDispatcherBase
} // namespace Private } // namespace Private
@ -215,16 +247,11 @@ namespace Private
class TypesRhs = TypesLhs, class TypesRhs = TypesLhs,
typename ResultType = Loki::Private::VoidWrap::type typename ResultType = Loki::Private::VoidWrap::type
> >
class StaticDispatcher : public ::Loki::Select class StaticDispatcher : public ::Loki::Private::StaticDispatcherBase
< <
::Loki::Private::IsVoid<ResultType>::value, Executor, BaseLhs, TypesLhs, symmetric,
::Loki::Private::StaticDispatcherVoidBase<Executor, BaseRhs, TypesRhs, ResultType
BaseLhs, TypesLhs, symmetric, BaseRhs, >::Base
TypesRhs>,
::Loki::Private::StaticDispatcherBase<Executor,
BaseLhs, TypesLhs, symmetric, BaseRhs,
TypesRhs, ResultType>
>::Result
{ {
public: public:
@ -238,27 +265,29 @@ namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Private namespace Private
{ {
// Implementation for result types != void
template <class BaseLhs, class BaseRhs, typename ResultType, template <class BaseLhs, class BaseRhs, typename ResultType,
typename CallbackType> struct BasicDispatcherBase; typename CallbackType>
class 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: private:
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun); // Common (independent of the result type) code for BasicDispatcher
bool DoRemove(TypeInfo lhs, TypeInfo rhs); class Common
{
private:
void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)
{
callbackMap_[KeyType(lhs, rhs)] = fun;
}
bool DoRemove(TypeInfo lhs, TypeInfo rhs)
{
return callbackMap_.erase(KeyType(lhs, rhs)) == 1;
}
protected: protected:
typedef std::pair<TypeInfo,TypeInfo> KeyType; typedef std::pair<TypeInfo,TypeInfo> KeyType;
typedef CallbackType MappedType; typedef CallbackType MappedType;
typedef AssocVector<KeyType, MappedType> MapType; typedef AssocVector<KeyType, MappedType> MapType;
MapType callbackMap_; MapType callbackMap_;
~BasicDispatcherCommonBase() {} ~Common() {}
public: public:
template <class SomeLhs, class SomeRhs> template <class SomeLhs, class SomeRhs>
void Add(CallbackType fun, ::Loki::Type2Type<SomeLhs>, void Add(CallbackType fun, ::Loki::Type2Type<SomeLhs>,
@ -273,76 +302,46 @@ namespace Private
{ {
return DoRemove(typeid(SomeLhs), typeid(SomeRhs)); return DoRemove(typeid(SomeLhs), typeid(SomeRhs));
} }
}; // Common
}; template <class R> // Base for ResultType != void
class In : public Common
// 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; public:
} ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
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);
protected:
~BasicDispatcherBase() {}
};
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::key_type k(typeid(lhs),typeid(rhs));
typename MapType::iterator i = Base::callbackMap_.find(k); typename MapType::iterator i = Common::callbackMap_.find(k);
if (i == Base::callbackMap_.end()) if (i == Common::callbackMap_.end())
{ {
throw std::runtime_error("Function not found"); throw std::runtime_error("Function not found");
} }
return (i->second)(lhs, rhs); 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);
protected: protected:
~BasicDispatcherVoidBase() {} ~In() {}
}; }; // In
template <class BaseLhs, class BaseRhs, typename CallbackType> template <> // Base for ResultType == void
typename BasicDispatcherVoidBase<BaseLhs,BaseRhs, CallbackType>::ResultType class In<void> : public Common
BasicDispatcherVoidBase<BaseLhs,BaseRhs, CallbackType> {
::Go(BaseLhs& lhs, BaseRhs& rhs) public:
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{ {
typename MapType::key_type k(typeid(lhs),typeid(rhs)); typename MapType::key_type k(typeid(lhs),typeid(rhs));
typename MapType::iterator i = Base::callbackMap_.find(k); typename MapType::iterator i = Common::callbackMap_.find(k);
if (i == Base::callbackMap_.end()) if (i == Common::callbackMap_.end())
{ {
throw std::runtime_error("Function not found"); throw std::runtime_error("Function not found");
} }
(i->second)(lhs, rhs); (i->second)(lhs, rhs);
} }
protected:
~In<void>() {}
}; // In
public:
typedef In<ResultType> Base;
}; // BasicDispatcherBase
} // namespace Private } // namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -357,14 +356,10 @@ namespace Private
typename ResultType = Loki::Private::VoidWrap::type, typename ResultType = Loki::Private::VoidWrap::type,
typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&) typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
> >
class BasicDispatcher : public ::Loki::Select class BasicDispatcher : public ::Loki::Private::BasicDispatcherBase
< <
::Loki::Private::IsVoid<ResultType>::value, BaseLhs, BaseRhs, ResultType, CallbackType
::Loki::Private::BasicDispatcherVoidBase< >::Base
BaseLhs, BaseRhs, CallbackType>,
::Loki::Private::BasicDispatcherBase<
BaseLhs, BaseRhs, ResultType, CallbackType>
>::Result
{ {
public: public:
// member functions moved to base class // member functions moved to base class
@ -436,10 +431,16 @@ namespace Private
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
namespace Private namespace Private
{ {
template <typename ResultType, class BaseLhs, class BaseRhs, template <class BaseLhs, class BaseRhs, typename ResultType,
class DispatcherBackend> class DispatcherBackend>
struct FnDispatcherBase class FnDispatcherBase
{ {
private:
// Implementation for ResultType != void
template <class R>
class In
{
public:
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType, ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_; ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
@ -448,13 +449,13 @@ namespace Private
return backEnd_.Go(lhs, rhs); return backEnd_.Go(lhs, rhs);
} }
protected: protected:
~FnDispatcherBase() {} ~In() {}
}; }; // In
// Implementation for ResultType == void
template <class BaseLhs, class BaseRhs, class DispatcherBackend> template <>
struct FnDispatcherVoidBase class In<void>
{ {
typedef void ResultType; public:
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType, ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_; ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
@ -463,34 +464,37 @@ namespace Private
backEnd_.Go(lhs, rhs); backEnd_.Go(lhs, rhs);
} }
protected: protected:
~FnDispatcherVoidBase() {} ~In<void>() {}
}; }; // In<void>
public:
typedef In<ResultType> Base;
}; // FnDispatcherBase
template< class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs, template< class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
class CastLhs, class CastRhs, class ResultType, class CastLhs, class CastRhs,
void (*Callback)(SomeLhs&, SomeRhs&)> void (*Callback)(SomeLhs&, SomeRhs&)>
struct FnDispatcherHelperVoidBase class FnDispatcherHelperBase
{ {
typedef void ResultType; private:
template <class R>
class In
{
public:
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{ {
Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
} }
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs) static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
{ {
Trampoline(lhs, rhs); return Trampoline(lhs, rhs);
} }
protected: protected:
~FnDispatcherHelperVoidBase() {} ~In() {}
}; };
template <>
template<typename ResultType, class BaseLhs, class BaseRhs, class In<void>
class SomeLhs, class SomeRhs, class CastLhs, class CastRhs,
ResultType (*Callback)(SomeLhs&, SomeRhs&)>
struct FnDispatcherHelperBase
{ {
typedef void ResultType; public:
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs) static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{ {
Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
@ -500,7 +504,10 @@ namespace Private
Trampoline(lhs, rhs); Trampoline(lhs, rhs);
} }
protected: protected:
~FnDispatcherHelperBase() {} ~In<void>() {}
};
public:
typedef In<ResultType> Base;
}; };
template template
@ -509,46 +516,33 @@ namespace Private
typename ResultType, class CastLhs, class CastRhs, typename ResultType, class CastLhs, class CastRhs,
ResultType (*Callback)(SomeLhs&, SomeRhs&) ResultType (*Callback)(SomeLhs&, SomeRhs&)
> >
struct FnDispatcherHelper : public ::Loki::Select struct FnDispatcherHelper : public FnDispatcherHelperBase
< <
::Loki::Private::IsVoid<ResultType>::value, BaseLhs, BaseRhs, SomeLhs, SomeRhs,
FnDispatcherHelperVoidBase<BaseLhs, BaseRhs, ResultType, CastLhs, CastRhs, Callback
SomeLhs, SomeRhs, CastLhs, CastRhs, >::Base
Callback>,
FnDispatcherHelperBase<ResultType, BaseLhs, BaseRhs,
SomeLhs, SomeRhs, CastLhs, CastRhs,
Callback>
>::Result
{}; {};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// class template FnDispatcher // class template FnDispatcher
// Implements an automatic logarithmic double dispatcher for functions // Implements an automatic logarithmic double dispatcher for functions
// Features automated conversions // Features automated conversions
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
template <class BaseLhs, class BaseRhs = BaseLhs, template <class BaseLhs, class BaseRhs = BaseLhs,
typename ResultType = Loki::Private::VoidWrap::type, typename ResultType = Loki::Private::VoidWrap::type,
class CastingPolicy = DynamicCasterWrapper, class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper> class DispatcherBackend = BasicDispatcherWrapper>
class FnDispatcher : public ::Loki::Select class FnDispatcher : public ::Loki::Private::FnDispatcherBase
< <
::Loki::Private::IsVoid<ResultType>::value, BaseLhs, BaseRhs,
::Loki::Private::FnDispatcherVoidBase<BaseLhs, ResultType, DispatcherBackend
BaseRhs, DispatcherBackend>, >::Base
::Loki::Private::FnDispatcherBase<ResultType, BaseLhs,
BaseRhs, DispatcherBackend>
>::Result
{
typedef typename ::Loki::Select
<::Loki::Private::IsVoid<ResultType>::value,
::Loki::Private::FnDispatcherVoidBase<BaseLhs,
BaseRhs, DispatcherBackend>,
::Loki::Private::FnDispatcherBase<ResultType, BaseLhs,
BaseRhs, DispatcherBackend>
>::Result Base;
{
typedef typename ::Loki::Private::FnDispatcherBase
<
BaseLhs, BaseRhs, ResultType, DispatcherBackend
>::Base Base;
public: public:
template <class SomeLhs, class SomeRhs> template <class SomeLhs, class SomeRhs>
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&), void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&),
@ -559,43 +553,28 @@ namespace Private
::Loki::Type2Type<SomeRhs>()); ::Loki::Type2Type<SomeRhs>());
} }
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&)>
void Add(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs,
SomeLhs, SomeRhs,
ResultType,
typename ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local;
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&), bool symmetric = false>
void Add(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>, struct AddI
bool Symmetric) {
void operator()(FnDispatcher<BaseLhs, BaseRhs, ResultType,
CastingPolicy,DispatcherBackend>& f)
{ {
typedef Private::FnDispatcherHelper< typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs, BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType,
SomeLhs, SomeRhs, ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
ResultType, ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
typename ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
typename ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local; callback> Local;
f.Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>()); ::Loki::Type2Type<SomeRhs>());
if (Symmetric) if (symmetric)
{ {
Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(), f.Add(&Local::TrampolineR, ::Loki::Type2Type<SomeRhs>(),
::Loki::Type2Type<SomeRhs>()); ::Loki::Type2Type<SomeLhs>());
} }
} }
};
template <class SomeLhs, class SomeRhs> template <class SomeLhs, class SomeRhs>
void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>) void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
@ -618,7 +597,10 @@ namespace Private
{ {
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs, template <class BaseLhs, class BaseRhs, 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 FunctorDispatcherHelperBase
{
template <class R>
class In
{ {
Fun fun_; Fun fun_;
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>) ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
@ -630,20 +612,17 @@ namespace Private
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
} }
public: public:
FunctorDispatcherHelper(const Fun& fun) : fun_(fun) {} In(const Fun& fun) : fun_(fun) {}
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs) ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
{ {
return Fire(lhs,rhs,Int2Type<SwapArgs>()); return Fire(lhs,rhs,Int2Type<SwapArgs>());
} }
}; };
template <>
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs, class In<void>
class CastLhs, class CastRhs, class Fun, bool SwapArgs>
class FunctorDispatcherHelperVoid
{ {
Fun fun_; Fun fun_;
typedef void ResultType;
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>) ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
{ {
fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
@ -653,17 +632,43 @@ namespace Private
fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs)); fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
} }
public: public:
FunctorDispatcherHelperVoid(const Fun& fun) : fun_(fun) {} In<void>(const Fun& fun) : fun_(fun) {}
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs) ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
{ {
Fire(lhs,rhs,Int2Type<SwapArgs>()); Fire(lhs,rhs,Int2Type<SwapArgs>());
} }
}; };
public:
typedef In<ResultType> Base;
}; // FunctorDispatcherHelperBase
template <class BaseLhs, class BaseRhs, typename ResultType, template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
typename ResultType, class CastLhs, class CastRhs, class Fun, bool SwapArgs>
class FunctorDispatcherHelper : public FunctorDispatcherHelperBase
<
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
ResultType, CastLhs, CastRhs, Fun,
SwapArgs
>::Base
{
private:
typedef typename FunctorDispatcherHelperBase
<
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
ResultType, CastLhs, CastRhs, Fun, SwapArgs
>::Base Base;
public:
FunctorDispatcherHelper(const Fun& f) : Base(f)
{}
};
template <typename ResultType, class BaseLhs, class BaseRhs,
class DispatcherBackend> class DispatcherBackend>
class FunctorDispatcherCommonBase class FunctorDispatcherBase
{
private:
class Common
{ {
protected: protected:
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList; typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
@ -671,46 +676,39 @@ namespace Private
ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType, ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType,
FunctorType>::type backEnd_; FunctorType>::type backEnd_;
~FunctorDispatcherCommonBase() {} ~Common() {}
}; };
template <typename ResultType, class BaseLhs, class BaseRhs, template <class R>
class DispatcherBackend> class In : public Common
class FunctorDispatcherBase : public FunctorDispatcherCommonBase<BaseLhs,
BaseRhs, ResultType, DispatcherBackend>
{ {
typedef FunctorDispatcherCommonBase<BaseLhs, BaseRhs, ResultType,
DispatcherBackend> Base;
public: public:
typedef typename Base::ArgsList ArgsList; typedef typename Common::ArgsList ArgsList;
typedef typename Base::FunctorType FunctorType; typedef typename Common::FunctorType FunctorType;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs) ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{ {
return Base::backEnd_.Go(lhs, rhs); return Common::backEnd_.Go(lhs, rhs);
} }
protected: protected:
~FunctorDispatcherBase() {} In() {}
}; };
template <>
template <class BaseLhs, class BaseRhs, class DispatcherBackend> class In<void> : public Common
class FunctorDispatcherVoidBase : public FunctorDispatcherCommonBase<BaseLhs,
BaseRhs, void, DispatcherBackend>
{ {
typedef void ResultType;
typedef FunctorDispatcherCommonBase<BaseLhs, BaseRhs, ResultType,
DispatcherBackend> Base;
public: public:
typedef typename Base::ArgsList ArgsList; typedef typename Common::ArgsList ArgsList;
typedef typename Base::FunctorType FunctorType; typedef typename Common::FunctorType FunctorType;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs) ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{ {
Base::backEnd_.Go(lhs, rhs); Common::backEnd_.Go(lhs, rhs);
} }
protected: protected:
~FunctorDispatcherVoidBase() {} In<void>() {}
}; };
public:
typedef In<ResultType> Base;
};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -723,23 +721,15 @@ namespace Private
typename ResultType = Loki::Private::VoidWrap::type, typename ResultType = Loki::Private::VoidWrap::type,
class CastingPolicy = DynamicCasterWrapper, class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper> class DispatcherBackend = BasicDispatcherWrapper>
class FunctorDispatcher : public ::Loki::Select class FunctorDispatcher : public ::Loki::Private::FunctorDispatcherBase
< <
::Loki::Private::IsVoid<ResultType>::value, ResultType, BaseLhs, BaseRhs, DispatcherBackend
::Loki::Private::FunctorDispatcherVoidBase<BaseLhs, >::Base
BaseRhs, DispatcherBackend>,
::Loki::Private::FunctorDispatcherBase<ResultType,
BaseLhs, BaseRhs, DispatcherBackend>
>::Result
{ {
typedef typename ::Loki::Select typedef typename ::Loki::Private::FunctorDispatcherBase
< <
::Loki::Private::IsVoid<ResultType>::value, ResultType, BaseLhs, BaseRhs, DispatcherBackend
::Loki::Private::FunctorDispatcherVoidBase<BaseLhs, BaseRhs, >::Base Base;
DispatcherBackend>,
::Loki::Private::FunctorDispatcherBase<ResultType, BaseLhs, BaseRhs,
DispatcherBackend>
>::Result Base;
public: public:
typedef Base::ArgsList ArgsList; typedef Base::ArgsList ArgsList;
typedef Base::FunctorType FunctorType; typedef Base::FunctorType FunctorType;
@ -749,13 +739,12 @@ namespace Private
{ {
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 typename Select< typedef typename
Private::IsVoid<ResultType>::value, Private::FunctorDispatcherHelper
Private::FunctorDispatcherHelperVoid<BaseLhs, BaseRhs, SomeLhs, <
SomeRhs, CastOne,CastTwo,Fun, false>, BaseLhs, BaseRhs, SomeLhs, SomeRhs,
Private::FunctorDispatcherHelper<BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType,CastOne,CastTwo,Fun, false
ResultType,CastOne,CastTwo,Fun, false> >::Base Adapter;
>::Result Adapter;
Base::backEnd_.Add(FunctorType(Adapter(fun), Loki::Disambiguate()), Base::backEnd_.Add(FunctorType(Adapter(fun), Loki::Disambiguate()),
Type2Type<SomeLhs>(), Type2Type<SomeRhs>()); Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
} }
@ -770,15 +759,15 @@ namespace Private
// Note: symmetry only makes sense where BaseLhs==BaseRhs // Note: symmetry only makes sense where BaseLhs==BaseRhs
typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne; typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type CastTwo; typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type CastTwo;
typedef typename Select<Private::IsVoid<ResultType>::value, typedef typename
Private::FunctorDispatcherHelperVoid<BaseLhs, BaseLhs, Private::FunctorDispatcherHelper
SomeLhs, SomeRhs, CastOne,CastTwo, Fun, true>, <
Private::FunctorDispatcherHelper<BaseLhs, BaseLhs, BaseLhs, BaseRhs, SomeLhs, SomeRhs,
ResultType, SomeLhs, SomeRhs,CastOne, CastTwo,Fun, true> ResultType,CastOne,CastTwo,Fun, true
>::Result AdapterR; >::Base AdapterR;
Base::backEnd_.Add(FunctorType(Adapter(fun)), Base::backEnd_.Add(FunctorType(AdapterR(fun), Loki::Disambiguate()),
Type2Type<SomeLhs>(), Type2Type<SomeRhs>()); Type2Type<SomeRhs>(), Type2Type<SomeLhs>());
} }
} }
@ -803,6 +792,9 @@ namespace Private
// support for return type void. B.K. // support for return type void. B.K.
// Mar 06, 2003: Changed default values for return types to void. // Mar 06, 2003: Changed default values for return types to void.
// Added protected destructors to private implementation classes B.K. // Added protected destructors to private implementation classes B.K.
// Mar 20. 2003: Fixed Bugs in FnDispatcherHelperBase, FnDispatcher::Add and
// FunctorDispatcher::Add.
// New Interface for FnDispatcher::Add.B.K.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#endif #endif