multimethods.h

来自「C++封装的视频采集代码」· C头文件 代码 · 共 463 行 · 第 1/2 页

H
463
字号
////////////////////////////////////////////////////////////////////////////////// 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-Wesley 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: August 9, 2002#ifndef MULTIMETHODS_INC_#define MULTIMETHODS_INC_#include "Typelist.h"#include "LokiTypeInfo.h" //### BCB#include "Functor.h"#include "AssocVector.h"//#include <iostream> // ***#include "SysLib/xdbg.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{////////////////////////////////////////////////////////////////////////////////// class template InvocationTraits (helper)// Helps implementing optional symmetry////////////////////////////////////////////////////////////////////////////////    namespace Private    {/* ### BCB checks existence Fire(rhs, lhs) even when this function is not needed, fails to compile        template <class SomeLhs, class SomeRhs,			class Executor, typename ResultType>        struct InvocationTraits        {            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 <class SomeLhs, class SomeRhs, class Executor, typenameResultType>        struct NormalInvocation        {            static ResultType DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec)            {                return exec.Fire(lhs, rhs);            }        };        template <class SomeLhs, class SomeRhs, class Executor, typename ResultType>        struct SwappedInvocation        {            static ResultType DoDispatch(SomeLhs& lhs, SomeRhs& rhs, Executor& exec)            {                return exec.Fire(rhs, lhs);            }        };    }////////////////////////////////////////////////////////////////////////////////// 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 = void    >    class StaticDispatcher    {        template <class SomeLhs>        static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,            Executor exec, NullType)        { return exec.OnError(lhs, rhs); }        template <class TList, class SomeLhs>        static ResultType DispatchRhs(SomeLhs& lhs, BaseRhs& rhs,            Executor exec, TList)        {            typedef typename TList::Head Head;            typedef typename TList::Tail Tail;            if (Head* p2 = dynamic_cast<Head*>(&rhs))            {                //### BCB - original statement was too complex for this compiler                enum { val1 = int(TL::IndexOf<TypesRhs, Head>::value) };                enum { val2 = int(TL::IndexOf<TypesLhs, SomeLhs>::value) };                enum { val3 = symmetric && (val1 < val2) };                // BCB doesn't properly converts enum to bool                enum { val4 = val3 != 0 };                const bool val5 = (val4 == 0) ? false : true; // it must be so clumsy                typedef Private::NormalInvocation<SomeLhs, Head, Executor, ResultType> t1;                typedef Private::SwappedInvocation<SomeLhs, Head, Executor, ResultType> t2;                typedef Select<val4, t1, t2>::Result invocation_t;                return invocation_t::DoDispatch(lhs, *p2, exec);            }            return DispatchRhs(lhs, rhs, exec, Tail());        }        static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,            Executor exec, NullType)        { return exec.OnError(lhs, rhs); }        template <class TList>        static ResultType DispatchLhs(BaseLhs& lhs, BaseRhs& rhs,            Executor exec, TList)        {            typedef typename TList::Head Head;            typedef typename TList::Tail Tail;            if (Head* p1 = dynamic_cast<Head*>(&lhs))            {                return DispatchRhs(*p1, rhs, exec, TypesRhs());            }            return DispatchLhs(lhs, rhs, exec, Tail());        }    public:        static ResultType Go(BaseLhs& lhs, BaseRhs& rhs,            Executor exec)        { return DispatchLhs(lhs, rhs, exec, TypesLhs()); }    };////////////////////////////////////////////////////////////////////////////////// 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 = void,        typename CallbackType = ResultType (*)(BaseLhs&, BaseRhs&)    >    class BasicDispatcher    {        typedef std::pair<TypeInfo,TypeInfo> KeyType;        typedef CallbackType MappedType;        typedef AssocVector<KeyType, MappedType> MapType;        MapType callbackMap_;        void DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun);        bool DoRemove(TypeInfo lhs, TypeInfo rhs);    public:        template <class SomeLhs, class SomeRhs>        void Add(CallbackType fun)        {            DoAdd(typeid(SomeLhs), typeid(SomeRhs), fun);        }        template <class SomeLhs, class SomeRhs>        bool Remove()        {            return DoRemove(typeid(SomeLhs), typeid(SomeRhs));        }        ResultType Go(BaseLhs& lhs, BaseRhs& rhs);    };    // Non-inline to reduce compile time overhead...    template <class BaseLhs, class BaseRhs,		typename ResultType, typename CallbackType>    void BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>    	 ::DoAdd(TypeInfo lhs, TypeInfo rhs, CallbackType fun)    {        callbackMap_[KeyType(lhs, rhs)] = fun;    }    template <class BaseLhs, class BaseRhs,		typename ResultType, typename CallbackType>    bool BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>         ::DoRemove(TypeInfo lhs, TypeInfo rhs)    {        return callbackMap_.erase(KeyType(lhs, rhs)) == 1;    }    template <class BaseLhs, class BaseRhs,		typename ResultType, typename CallbackType>    ResultType BasicDispatcher<BaseLhs,BaseRhs,ResultType,CallbackType>               ::Go(BaseLhs& lhs, BaseRhs& rhs)    {    	typename MapType::key_type k(typeid(lhs),typeid(rhs));        typename MapType::iterator i = callbackMap_.find(k);        if (i == callbackMap_.end())        {//            std::cout << "Function not found\n";            TRACE("Loki/MultiMethods.h BasicDispatcher - Function not found \n");            //                throw std::runtime_error("Function not found");        }        return (i->second)(lhs, rhs);    }////////////////////////////////////////////////////////////////////////////////// class template StaticCaster// Implementation of the CastingPolicy used by FunctorDispatcher

⌨️ 快捷键说明

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