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 + -
显示快捷键?