📄 multimethods.h
字号:
};
};
////////////////////////////////////////////////////////////////////////////////
// class template Private::FnDispatcherHelper
// Implements trampolines and argument swapping used by FnDispatcher
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class BaseLhs, class BaseRhs, typename ResultType,
class DispatcherBackend>
class FnDispatcherBase
{
private:
// Implementation for ResultType != void
template <class R>
class In
{
public:
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
return backEnd_.Go(lhs, rhs);
}
protected:
~In() {}
}; // In
// Implementation for ResultType == void
template <>
class In<void>
{
public:
ApplyInnerType4<DispatcherBackend, BaseLhs, BaseRhs, ResultType,
ResultType (*)(BaseLhs&, BaseRhs&)>::type backEnd_;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
backEnd_.Go(lhs, rhs);
}
protected:
~In<void>() {}
}; // In<void>
public:
typedef In<ResultType> Base;
}; // FnDispatcherBase
template< class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
class ResultType, class CastLhs, class CastRhs,
void (*Callback)(SomeLhs&, SomeRhs&)>
class FnDispatcherHelperBase
{
private:
template <class R>
class In
{
public:
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{
return Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
{
return Trampoline(lhs, rhs);
}
protected:
~In() {}
};
template <>
class In<void>
{
public:
static ResultType Trampoline(BaseLhs& lhs, BaseRhs& rhs)
{
Callback(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
static ResultType TrampolineR(BaseRhs& rhs, BaseLhs& lhs)
{
Trampoline(lhs, rhs);
}
protected:
~In<void>() {}
};
public:
typedef In<ResultType> Base;
};
template
<
class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
typename ResultType, class CastLhs, class CastRhs,
ResultType (*Callback)(SomeLhs&, SomeRhs&)
>
struct FnDispatcherHelper : public FnDispatcherHelperBase
<
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
ResultType, CastLhs, CastRhs, Callback
>::Base
{};
}
////////////////////////////////////////////////////////////////////////////////
// class template FnDispatcher
// Implements an automatic logarithmic double dispatcher for functions
// Features automated conversions
////////////////////////////////////////////////////////////////////////////////
template <class BaseLhs, class BaseRhs = BaseLhs,
typename ResultType = Loki::Private::VoidWrap::type,
class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper>
class FnDispatcher : public ::Loki::Private::FnDispatcherBase
<
BaseLhs, BaseRhs,
ResultType, DispatcherBackend
>::Base
{
typedef typename ::Loki::Private::FnDispatcherBase
<
BaseLhs, BaseRhs, ResultType, DispatcherBackend
>::Base Base;
public:
template <class SomeLhs, class SomeRhs>
void Add(ResultType (*pFun)(BaseLhs&, BaseRhs&),
::Loki::Type2Type<SomeLhs>,
::Loki::Type2Type<SomeRhs>)
{
Base::backEnd_.Add(pFun, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
}
// two different workarounds for FnDispatcher::Add
// Using the first one writes:
// DisType dispatcher;
// dispatcher.Add(DisType::Etas<SomeLhs, SomeRhs, &AFunc>());
// using the second workaround the call becomes:
// DisType dispatcher;
// DisTyp::AddI<SomeLhs, SomeRhs, &AFunc>()(dispatcher);
// Helper-class for the first workaround.
// When calling FnDispatcher::Add provide an object of this type
// as argument.
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric = false>
struct Etas
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType,
ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local;
enum {sym = symmetric};
typedef SomeLhs Lhs;
typedef SomeRhs Rhs;
};
// EtasType has to be a template parameter. If one tries to use
// a parameter of type Etas the MSVC 6.0 won't generate correct
// code.
template <class EtasType>
void Add(EtasType EtasObj)
{
typedef typename EtasType::Local Local;
typedef typename EtasType::Lhs SomeLhs;
typedef typename EtasType::Rhs SomeRhs;
Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
if (EtasType::sym)
{
Add(&Local::TrampolineR, ::Loki::Type2Type<SomeRhs>(),
::Loki::Type2Type<SomeLhs>());
}
}
// alternative workaround for FnDispatcher::Add
template <class SomeLhs, class SomeRhs,
ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric = false>
struct AddI
{
void operator()(FnDispatcher<BaseLhs, BaseRhs, ResultType,
CastingPolicy,DispatcherBackend>& f)
{
typedef Private::FnDispatcherHelper<
BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType,
ApplyInnerType2<CastingPolicy, SomeLhs,BaseLhs>::type,
ApplyInnerType2<CastingPolicy,SomeRhs,BaseRhs>::type,
callback> Local;
f.Add(&Local::Trampoline, ::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
if (symmetric)
{
f.Add(&Local::TrampolineR, ::Loki::Type2Type<SomeRhs>(),
::Loki::Type2Type<SomeLhs>());
}
}
};
template <class SomeLhs, class SomeRhs>
void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{
Base::backEnd_.Remove(::Loki::Type2Type<SomeLhs>(),
::Loki::Type2Type<SomeRhs>());
}
// moved to base class
// ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
};
////////////////////////////////////////////////////////////////////////////////
// class template FunctorDispatcherAdaptor
// permits use of FunctorDispatcher under gcc.2.95.2/3
///////////////////////////////////////////////////////////////////////////////
namespace Private
{
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs,
typename ResultType, class CastLhs, class CastRhs, class Fun, bool SwapArgs>
class FunctorDispatcherHelperBase
{
template <class R>
class In
{
Fun fun_;
ResultType Fire(BaseLhs& lhs, BaseRhs& rhs,Int2Type<false>)
{
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
ResultType Fire(BaseLhs& rhs, BaseRhs& lhs,Int2Type<true>)
{
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
}
public:
In(const Fun& fun) : fun_(fun) {}
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
{
return Fire(lhs,rhs,Int2Type<SwapArgs>());
}
};
template <>
class In<void>
{
Fun fun_;
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:
In<void>(const Fun& fun) : fun_(fun) {}
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
{
Fire(lhs,rhs,Int2Type<SwapArgs>());
}
};
public:
typedef In<ResultType> Base;
}; // FunctorDispatcherHelperBase
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 FunctorDispatcherBase
{
private:
class Common
{
protected:
typedef TYPELIST_2(BaseLhs&, BaseRhs&) ArgsList;
typedef Functor<ResultType, ArgsList, DEFAULT_THREADING> FunctorType;
ApplyInnerType4<DispatcherBackend,BaseLhs, BaseRhs, ResultType,
FunctorType>::type backEnd_;
~Common() {}
};
template <class R>
class In : public Common
{
public:
typedef typename Common::ArgsList ArgsList;
typedef typename Common::FunctorType FunctorType;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
return Common::backEnd_.Go(lhs, rhs);
}
protected:
In() {}
};
template <>
class In<void> : public Common
{
public:
typedef typename Common::ArgsList ArgsList;
typedef typename Common::FunctorType FunctorType;
ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
{
Common::backEnd_.Go(lhs, rhs);
}
protected:
In<void>() {}
};
public:
typedef In<ResultType> Base;
};
}
////////////////////////////////////////////////////////////////////////////////
// class template FunctorDispatcher
// Implements a logarithmic double dispatcher for functors
// Features automated casting
////////////////////////////////////////////////////////////////////////////////
template <class BaseLhs, class BaseRhs = BaseLhs,
typename ResultType = Loki::Private::VoidWrap::type,
class CastingPolicy = DynamicCasterWrapper,
class DispatcherBackend = BasicDispatcherWrapper>
class FunctorDispatcher : public ::Loki::Private::FunctorDispatcherBase
<
ResultType, BaseLhs, BaseRhs, DispatcherBackend
>::Base
{
typedef typename ::Loki::Private::FunctorDispatcherBase
<
ResultType, BaseLhs, BaseRhs, DispatcherBackend
>::Base Base;
public:
typedef Base::ArgsList ArgsList;
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,SomeRhs, BaseRhs>::type CastTwo;
typedef typename
Private::FunctorDispatcherHelper
<
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
ResultType,CastOne,CastTwo,Fun, false
>::Base Adapter;
Base::backEnd_.Add(FunctorType(Adapter(fun), Loki::Disambiguate()),
Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
}
template <class SomeLhs, class SomeRhs, class Fun>
void Add(const Fun& fun, ::Loki::Type2Type<SomeLhs>,
::Loki::Type2Type<SomeRhs>, bool symmetric)
{
Add(fun, Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
if (symmetric)
{
// Note: symmetry only makes sense where BaseLhs==BaseRhs
typedef typename ApplyInnerType2<CastingPolicy,SomeLhs, BaseLhs>::type CastOne;
typedef typename ApplyInnerType2<CastingPolicy,SomeRhs, BaseLhs>::type CastTwo;
typedef typename
Private::FunctorDispatcherHelper
<
BaseLhs, BaseRhs, SomeLhs, SomeRhs,
ResultType,CastOne,CastTwo,Fun, true
>::Base AdapterR;
Base::backEnd_.Add(FunctorType(AdapterR(fun), Loki::Disambiguate()),
Type2Type<SomeRhs>(), Type2Type<SomeLhs>());
}
}
template <class SomeLhs, class SomeRhs>
void Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
{
Base::backEnd_.Remove(Type2Type<SomeLhs>(), Type2Type<SomeRhs>());
}
// moved to base class
// ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
};
} // namespace Loki
////////////////////////////////////////////////////////////////////////////////
// Change log:
// 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)
// Oct 28, 2002: ported by Benjamin Kaufmann to MSVC 6
// Feb 19, 2003: replaced pointer-Dummies with Type2Type-Parameters and added
// support for return type void. B.K.
// Mar 06, 2003: Changed default values for return types to void.
// 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.
// Mar 21, 2003: Added new explicit template argument specification workaround
// for FnDispatcher::Add B.K.
////////////////////////////////////////////////////////////////////////////////
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -