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:
parent
273dc0d85e
commit
4d8052faa7
1 changed files with 453 additions and 461 deletions
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue