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

📄 multimethods.h

📁 loki库的源代码。loki库是以模板技术和面向对象技术为基础的c++类库。
💻 H
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////////////////////
// The Loki Library
// Copyright (c) 2001 by Andrei Alexandrescu
// This code accompanies the book:
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
// Permission to use, copy, modify, distribute and sell this software for any 
//     purpose is hereby granted without fee, provided that the above copyright 
//     notice appear in all copies and that both that copyright notice and this 
//     permission notice appear in supporting documentation.
// The author or Addison-Welsey Longman make no representations about the 
//     suitability of this software for any purpose. It is provided "as is" 
//     without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////

// Last update: Mar 21, 2003
// Added a new explicit template argument specification workaround for 
// FnDispatcher::Add which is more compliant with other 
// explicit template argument specification workarounds used in this port.
//
// Example usage:
// --------------
// Using the original library one writes:
// typedef FnDispatcher<Shape> Dispatcher;
// void Hatch(Rectangle& lhs, Poly& rhs) {...}
// 
// Dispatcher dis;
// disp.Add<Rectangle, Poly, &Hatch>();
//
// Using this port the example either becomes:
//	dis.Add(Dispatcher::Add<Rectangle, Poly, &Hatch>());
// or alternatively
//	Dispatcher::AddI<Rectangle, Poly, &Hatch>()(dis);
// 
// All dispatchers now have void as default value for return types.
// All dispatchers now support void as return type. 
// 
//
// The port now uses Tye2Type-parameters instead of plain pointers as
// a workaround of VC's explicit template argument specification bug.
// 
// For example:
// The original declaration of BasicDispatcher::Add looks like this:
//
//	template <class SomeLhs, class SomeRhs>
//	void Add(CallbackType fun);
// 
// and you call it like this:
//	obj.Add<Type1, Type2>(yourFun);
//
// This port uses:
//
//	template <class SomeLhs, class SomeRhs>
//	void Add(CallbackType fun, Type2Type<SomeLhs>, Type2Type<SomeRhs>);
//
// and you call it like this:
//	obj.Add(yourFun, Type2Type<Type1>(), Type2Type<Type2>());


#ifndef MULTIMETHODS_INC_
#define MULTIMETHODS_INC_

#include "Typelist.h"
#include "LokiTypeInfo.h"
#include "Functor.h"
#include "AssocVector.h"

////////////////////////////////////////////////////////////////////////////////
// IMPORTANT NOTE:
// The double dispatchers implemented below differ from the excerpts shown in
// the book - they are simpler while respecting the same interface.
////////////////////////////////////////////////////////////////////////////////

namespace Loki
{

////////////////////////////////////////////////////////////////////////////////
// Implementation helpers for StaticDispatcher
////////////////////////////////////////////////////////////////////////////////
	
namespace Private
{
	template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>
	struct InvocationTraitsBase
	{
	protected:
		template <class R>
		struct BaseImpl
		{
			static ResultType 
			DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec, Int2Type<false>)
			{
				return exec.Fire(lhs, rhs);
			}
			static ResultType DoDispatch(	SomeLhs& lhs, SomeRhs& rhs, 
											Executor& exec, Int2Type<true>)
			{
				return exec.Fire(rhs, lhs);
			}
		};
		template <>
		struct BaseImpl<void>
		{
			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);
			}
		};
	public:
		typedef BaseImpl<ResultType> Base;
	};
	template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>
	struct InvocationTraits : public InvocationTraitsBase
								<SomeLhs, SomeRhs, Executor, ResultType>::Base
	{
		
	};
	
	template<class Executor, class BaseLhs, class TypesLhs, bool symmetric,
		class BaseRhs, class TypesRhs, typename ResultType>
	class StaticDispatcherBase
	{
	private:
		// Base for ResultType != void
		template <class R>
		class In
		{
			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());
			}

		protected:
			~In() {}
		public:
			static ResultType Go(	BaseLhs& lhs, BaseRhs& rhs,
								Executor exec)
			{ return DispatchLhs(lhs, rhs, exec, TypesLhs()); }
		};	// In<R>
	
		// Base for ResultType == void
		template <>
		class In<void>
		{
			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::InvocationTraits< 
							SomeLhs, Head, Executor, void> 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());
			}

		protected:
			~In<void>() {}
		public:
			static ResultType Go(	BaseLhs& lhs, BaseRhs& rhs,
									Executor exec)
			{ DispatchLhs(lhs, rhs, exec, TypesLhs()); }
		};	// In<void>
	public:
		typedef In<ResultType> Base;
	};	// StaticDispatcherBase
	
}	// namespace Private

////////////////////////////////////////////////////////////////////////////////
// class template StaticDispatcher
// Implements an automatic static double dispatcher based on two typelists
////////////////////////////////////////////////////////////////////////////////
	template
    <
        class Executor,
        class BaseLhs, 
        class TypesLhs,
        bool symmetric = true,
        class BaseRhs = BaseLhs,
        class TypesRhs = TypesLhs,
        typename ResultType = Loki::Private::VoidWrap::type
    >
    class StaticDispatcher : public ::Loki::Private::StaticDispatcherBase
								<
									Executor, BaseLhs, TypesLhs, symmetric, 
									BaseRhs,  TypesRhs, ResultType
								>::Base
    {
        
    public:
        // member functions moved to base class
		// static ResultType Go(	BaseLhs& lhs, BaseRhs& rhs,
		// 							Executor exec)
    };    

////////////////////////////////////////////////////////////////////////////////
// Implementation helpers for BasicDispatcher
////////////////////////////////////////////////////////////////////////////////
namespace Private
{
	template <class BaseLhs, class BaseRhs, typename ResultType,
		typename CallbackType> 
	class BasicDispatcherBase
	{
	private:
		// Common (independent of the result type) code for BasicDispatcher
		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:
			typedef std::pair<TypeInfo,TypeInfo> KeyType;
			typedef CallbackType MappedType;
			typedef AssocVector<KeyType, MappedType> MapType;
			MapType callbackMap_;
			~Common() {}
		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));
			}
		};	// Common
		template <class R>	// Base for ResultType != void
		class In : public Common
		{
		public:	
			ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
			{
				typename MapType::key_type k(typeid(lhs),typeid(rhs));
				typename MapType::iterator i = Common::callbackMap_.find(k);
				if (i == Common::callbackMap_.end())
				{
					throw std::runtime_error("Function not found");
				}
				return (i->second)(lhs, rhs);
			}
		protected:
			~In() {}	
		};	// In
		template <>	// Base for ResultType == void
		class In<void> : public Common
		{
		public:	
			ResultType Go(BaseLhs& lhs, BaseRhs& rhs)
			{
				typename MapType::key_type k(typeid(lhs),typeid(rhs));
				typename MapType::iterator i = Common::callbackMap_.find(k);
				if (i == Common::callbackMap_.end())
				{
					throw std::runtime_error("Function not found");
				}
				(i->second)(lhs, rhs);
			}
		protected:
			~In<void>() {}	
		};	// In
		
	public:
		typedef In<ResultType> Base;
	};	// BasicDispatcherBase
	
} // namespace Private

////////////////////////////////////////////////////////////////////////////////
// class template BasicDispatcher
// Implements a logarithmic double dispatcher for functors (or functions)
// Doesn't offer automated casts or symmetry
////////////////////////////////////////////////////////////////////////////////
	template
    <
        class BaseLhs,
        class BaseRhs = BaseLhs,
        typename ResultType = Loki::Private::VoidWrap::type,
        typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)
    >
    class BasicDispatcher : public ::Loki::Private::BasicDispatcherBase
							<
								BaseLhs, BaseRhs, ResultType, CallbackType
							>::Base
    {
        public:
			// member functions moved to base class
			// template <class SomeLhs, class SomeRhs>
			// void Add(CallbackType fun,	::Loki::Type2Type<SomeLhs>,
			//								::Loki::Type2Type<SomeRhs>)
			//
			// template <class SomeLhs, class SomeRhs>
			// bool Remove(::Loki::Type2Type<SomeLhs>, ::Loki::Type2Type<SomeRhs>)
			//
			// ResultType Go(BaseLhs& lhs, BaseRhs& rhs);
    };


	struct BasicDispatcherWrapper
	{
		template <class T, class U, class V, class W>
		struct In
		{
			typedef BasicDispatcher<T, U, V, W> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// class template StaticCaster
// Implementation of the CastingPolicy used by FunctorDispatcher
////////////////////////////////////////////////////////////////////////////////

    template <class To, class From>
    struct StaticCaster
    {
        static To& Cast(From& obj)
        {
            return static_cast<To&>(obj);
        }
    };
	struct StaticCasterWrapper
	{
		template <class T, class U>
		struct In
		{
			typedef StaticCaster<T, U> type;
		};
	};
////////////////////////////////////////////////////////////////////////////////
// class template DynamicCaster
// Implementation of the CastingPolicy used by FunctorDispatcher
////////////////////////////////////////////////////////////////////////////////

    template <class To, class From>
    struct DynamicCaster
    {
        static To& Cast(From& obj)
        {
			return dynamic_cast<To&>(obj);
        }
    };
	struct DynamicCasterWrapper
	{
		template <class T, class U>
		struct In
		{
			typedef DynamicCaster<T, U> type;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -