VTK
dox/Common/DataModel/vtkDoubleDispatcher.h
Go to the documentation of this file.
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