⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multimethods.h

📁 loki库的源代码。loki库是以模板技术和面向对象技术为基础的c++类库。
💻 H
📖 第 1 页 / 共 2 页
字号:
		};
	};

////////////////////////////////////////////////////////////////////////////////
// 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 + -