VTK
|
00001 /*========================================================================= 00002 00003 Program: Visualization Toolkit 00004 Module: vtkDoubleDispatcher.h 00005 00006 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 00007 All rights reserved. 00008 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00015 00017 // The Loki Library 00018 // Copyright (c) 2001 by Andrei Alexandrescu 00019 // This code accompanies the book: 00020 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 00021 // Patterns Applied". Copyright (c) 2001. Addison-Wesley. 00022 // Permission to use, copy, modify, distribute and sell this software for any 00023 // purpose is hereby granted without fee, provided that the above copyright 00024 // notice appear in all copies and that both that copyright notice and this 00025 // permission notice appear in supporting documentation. 00026 // The author or Addison-Wesley Longman make no representations about the 00027 // suitability of this software for any purpose. It is provided "as is" 00028 // without express or implied warranty. 00030 00072 #ifndef __vtkDoubleDispatcher_h 00073 #define __vtkDoubleDispatcher_h 00074 00075 #include "vtkDispatcher_Private.h" //needed for Functor,CastingPolicy,TypeInfo 00076 #include <map> //Required for the storage of template params to runtime params 00077 00078 template 00079 < 00080 class BaseLhs, 00081 class BaseRhs = BaseLhs, 00082 typename ReturnType = void, 00083 template <class, class> class CastingPolicy = vtkDispatcherCommon::vtkCaster 00084 > 00085 class vtkDoubleDispatcher 00086 { 00087 public: 00089 00098 template <class SomeLhs, class SomeRhs, class Functor> 00099 void Add(Functor fun) { this->AddInternal<SomeLhs,SomeRhs>(fun, 1); } 00101 00103 00105 template <class SomeLhs, class SomeRhs> 00106 bool Remove() { return DoRemove(typeid(SomeLhs), typeid(SomeRhs)); } 00108 00120 ReturnType Go(BaseLhs* lhs, BaseRhs* rhs); 00121 00122 protected: 00123 typedef vtkDispatcherCommon::TypeInfo TypeInfo; 00124 typedef vtkDoubleDispatcherPrivate::Functor<ReturnType,BaseLhs,BaseRhs> 00125 MappedType; 00126 00127 void DoAddFunctor(TypeInfo lhs,TypeInfo rhs, MappedType fun); 00128 bool DoRemove(TypeInfo lhs, TypeInfo rhs); 00129 00130 typedef std::pair<TypeInfo,TypeInfo> KeyType; 00131 typedef std::map<KeyType, MappedType > MapType; 00132 MapType FunctorMap; 00133 private: 00134 template <class SomeLhs, class SomeRhs, class Functor> 00135 void AddInternal(const Functor& fun, long); 00136 template <class SomeLhs, class SomeRhs, class Functor> 00137 void AddInternal(Functor* fun, int); 00138 }; 00139 00140 //We are making all these method non-inline to reduce compile time overhead 00141 //---------------------------------------------------------------------------- 00142 template<class BaseLhs, class BaseRhs, typename ReturnType, 00143 template <class, class> class CastingPolicy> 00144 template <class SomeLhs, class SomeRhs, class Functor> 00145 void vtkDoubleDispatcher<BaseLhs,BaseRhs,ReturnType,CastingPolicy> 00146 ::AddInternal(const Functor& fun, long) 00147 { 00148 typedef vtkDoubleDispatcherPrivate::FunctorDoubleDispatcherHelper< 00149 BaseLhs, BaseRhs, 00150 SomeLhs, SomeRhs, 00151 ReturnType, 00152 CastingPolicy<SomeLhs, BaseLhs>, 00153 CastingPolicy<SomeRhs, BaseRhs>, 00154 Functor> Adapter; 00155 Adapter ada(fun); 00156 MappedType mt(ada); 00157 DoAddFunctor(typeid(SomeLhs), typeid(SomeRhs),mt); 00158 } 00159 00160 //---------------------------------------------------------------------------- 00161 template<class BaseLhs, class BaseRhs, typename ReturnType, 00162 template <class, class> class CastingPolicy> 00163 template <class SomeLhs, class SomeRhs, class Functor> 00164 void vtkDoubleDispatcher<BaseLhs,BaseRhs,ReturnType,CastingPolicy> 00165 ::AddInternal(Functor* fun, int) 00166 { 00167 typedef vtkDoubleDispatcherPrivate::FunctorRefDispatcherHelper< 00168 BaseLhs, BaseRhs, 00169 SomeLhs, SomeRhs, 00170 ReturnType, 00171 CastingPolicy<SomeLhs, BaseLhs>, 00172 CastingPolicy<SomeRhs, BaseRhs>, 00173 Functor> Adapter; 00174 Adapter ada(*fun); 00175 MappedType mt(ada); 00176 DoAddFunctor(typeid(SomeLhs), typeid(SomeRhs),mt); 00177 } 00178 00179 //---------------------------------------------------------------------------- 00180 template<class BaseLhs, class BaseRhs, typename ReturnType, 00181 template <class, class> class CastingPolicy> 00182 void vtkDoubleDispatcher<BaseLhs,BaseRhs,ReturnType,CastingPolicy> 00183 ::DoAddFunctor(TypeInfo lhs, TypeInfo rhs, MappedType fun) 00184 { 00185 FunctorMap[KeyType(lhs, rhs)] = fun; 00186 } 00187 00188 //---------------------------------------------------------------------------- 00189 template <class BaseLhs, class BaseRhs, typename ReturnType, 00190 template <class, class> class CastingPolicy> 00191 bool vtkDoubleDispatcher<BaseLhs,BaseRhs,ReturnType,CastingPolicy> 00192 ::DoRemove(TypeInfo lhs, TypeInfo rhs) 00193 { 00194 return FunctorMap.erase(KeyType(lhs, rhs)) == 1; 00195 } 00196 00197 //---------------------------------------------------------------------------- 00198 template <class BaseLhs, class BaseRhs, typename ReturnType, 00199 template <class, class> class CastingPolicy> 00200 ReturnType vtkDoubleDispatcher<BaseLhs,BaseRhs,ReturnType,CastingPolicy> 00201 ::Go(BaseLhs* lhs, BaseRhs* rhs) 00202 { 00203 typename MapType::key_type k(typeid(*lhs),typeid(*rhs)); 00204 typename MapType::iterator i = FunctorMap.find(k); 00205 if (i == FunctorMap.end()) 00206 { 00207 //we don't want to throw exceptions so we have two options. 00208 //we can return the default, or make a lightweight struct for return value 00209 return ReturnType(); 00210 } 00211 return (i->second)(*lhs,*rhs); 00212 } 00213 00214 #endif // __vtkDoubleDispatcher_h 00215 // VTK-HeaderTest-Exclude: vtkDoubleDispatcher.h