User Manual, Developers Guide and API Documentation

DoubleDispatcher.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 
00029 #ifndef WNS_DOUBLEDISPATCHER_HPP
00030 #define WNS_DOUBLEDISPATCHER_HPP
00031 #include <WNS/TypeInfo.hpp>
00032 #include <WNS/TypeTraits.hpp>
00033 #include <WNS/SmartPtr.hpp>
00034 #include <string>
00035 #include <map>
00036 #include <iostream>
00037 
00038 namespace wns
00039 {
00043     template<typename PlainBaseRhs,
00044          typename CallbackType>
00045     class DoubleDispatcherBase
00046     {
00047         friend class DoubleDispatcherTest;
00048     public:
00049         typedef std::map<TypeInfo, CallbackType> CallbackMap;
00050         typedef typename CallbackMap::iterator CMI;
00051 
00052         DoubleDispatcherBase()
00053             : cm(CallbackMap()),
00054               defaultCallback(0)
00055         {
00056         }
00057 
00058         virtual ~DoubleDispatcherBase()
00059         {}
00060 
00061     protected:
00062         CallbackType
00063         getCallback(const TypeInfo& rhs)
00064         {
00065             CMI res = cm.find(rhs);
00066             if(res!=cm.end()) {
00067                 return res->second;
00068             } else {
00069                 assert(defaultCallback);
00070                 return defaultCallback;
00071             }
00072         }
00073 
00074         void
00075         addCallback(const TypeInfo& rhs, const CallbackType& cb)
00076         {
00077             if(rhs == TypeInfo::create<PlainBaseRhs>()) {
00078                 defaultCallback = cb;
00079             } else {
00080                 assert(!cm.count(rhs));
00081                 cm[rhs] = cb;
00082             };
00083         }
00084 
00085         void
00086         addDefaultCallback(const CallbackType& cb) {
00087             defaultCallback = cb;
00088         }
00089 
00090     private:
00091         CallbackMap cm;
00092         CallbackType defaultCallback;
00093     };
00094 
00102     template<class ConcreteLhs,
00103          class BaseRhs,
00104          typename ResultType = void,
00105          int Argument = TypeTraits<BaseRhs>::propNumber>
00106     class DoubleDispatcher
00107     {
00108     };
00109 
00110     template<class ConcreteLhs,
00111          class BaseRhs,
00112          typename ResultType>
00113     class DoubleDispatcher<ConcreteLhs,
00114                    BaseRhs,
00115                    ResultType,
00116                    TypeTraits<NullType>::Reference>
00117                        : public DoubleDispatcherBase<typename TypeTraits<BaseRhs>::ReferenceType,
00118                                      ResultType (*)(ConcreteLhs&, BaseRhs)>
00119     {
00120     public:
00121         DoubleDispatcher()
00122             : DoubleDispatcherBase<typename TypeTraits<BaseRhs>::ReferenceType, ResultType (*)(ConcreteLhs&, BaseRhs)>()
00123             {
00124             }
00125         virtual ~DoubleDispatcher()
00126             {}
00127 
00128         template <typename ConcreteRhs,
00129             ResultType (ConcreteLhs::*callback)(ConcreteRhs&)>
00130             void
00131             addMemberFunction()
00132             {
00133                 struct Local
00134                 {
00135                     static ResultType Trampoline(ConcreteLhs& lhs, BaseRhs rhs)
00136                     {
00137                         return ((lhs).*callback)(static_cast<ConcreteRhs&>(rhs));
00138                     }
00139                 };
00140                 addCallback(TypeInfo::create<ConcreteRhs>(), &Local::Trampoline);
00141             }
00142 
00143         ResultType dispatch(ConcreteLhs& lhs, BaseRhs rhs)
00144             {
00145                 return (*getCallback(TypeInfo::create(rhs)))(lhs, rhs);
00146             }
00147 
00148         ResultType dispatch(ConcreteLhs* lhs, BaseRhs rhs)
00149             {
00150                 return (*getCallback(TypeInfo::create(rhs)))(*lhs, rhs);
00151             }
00152     };
00153 
00154     template<class ConcreteLhs,
00155          class BaseRhs,
00156          typename ResultType>
00157     class DoubleDispatcher<ConcreteLhs,
00158                    BaseRhs,
00159                    ResultType,
00160                    TypeTraits<NullType>::Pointer>
00161                        : public DoubleDispatcherBase<typename TypeTraits<BaseRhs>::PointeeType,
00162                                      ResultType (*)(ConcreteLhs&, BaseRhs)>
00163     {
00164     public:
00165         DoubleDispatcher()
00166             : DoubleDispatcherBase<typename TypeTraits<BaseRhs>::PointeeType, ResultType (*)(ConcreteLhs&, BaseRhs)>()
00167             {
00168             }
00169         virtual ~DoubleDispatcher()
00170             {}
00171 
00172         template <typename ConcreteRhs,
00173             ResultType (ConcreteLhs::*callback)(ConcreteRhs*)>
00174             void
00175             addMemberFunction()
00176             {
00177                 struct Local
00178                 {
00179                     static ResultType Trampoline(ConcreteLhs& lhs, BaseRhs rhs)
00180                     {
00181                         return ((lhs).*callback)(staticCast<ConcreteRhs>(rhs));
00182                     }
00183                 };
00184                 addCallback(TypeInfo::create<ConcreteRhs>(), &Local::Trampoline);
00185             }
00186 
00187         ResultType dispatch(ConcreteLhs& lhs, BaseRhs rhs)
00188             {
00189                 return (*getCallback(TypeInfo::create(*rhs)))(lhs, rhs);
00190             }
00191 
00192         ResultType dispatch(ConcreteLhs* lhs, BaseRhs rhs)
00193             {
00194                 return (*getCallback(TypeInfo::create(*rhs)))(*lhs, rhs);
00195             }
00196     };
00197 
00198     template<class ConcreteLhs,
00199          class BaseRhs,
00200          typename ResultType>
00201     class DoubleDispatcher<ConcreteLhs,
00202                    BaseRhs,
00203                    ResultType,
00204                    TypeTraits<NullType>::ConstReference>
00205                        : public DoubleDispatcherBase<typename TypeTraits<BaseRhs>::ReferenceType,
00206                                      ResultType (*)(ConcreteLhs&, BaseRhs)>
00207     {
00208     public:
00209         DoubleDispatcher()
00210             : DoubleDispatcherBase<typename TypeTraits<BaseRhs>::ReferenceType, ResultType (*)(ConcreteLhs&, BaseRhs)>()
00211             {
00212             }
00213         virtual ~DoubleDispatcher()
00214             {}
00215 
00216         template <typename ConcreteRhs,
00217             ResultType (ConcreteLhs::*callback)(const ConcreteRhs&)>
00218             void
00219             addMemberFunction()
00220             {
00221                 struct Local
00222                 {
00223                     static ResultType Trampoline(ConcreteLhs& lhs, BaseRhs rhs)
00224                     {
00225                         return ((lhs).*callback)(static_cast<const ConcreteRhs&>(rhs));
00226                     }
00227                 };
00228                 addCallback(TypeInfo::create<ConcreteRhs>(), &Local::Trampoline);
00229             }
00230 
00231         ResultType dispatch(ConcreteLhs& lhs, BaseRhs rhs)
00232             {
00233                 return (*getCallback(TypeInfo::create(rhs)))(lhs, rhs);
00234             }
00235 
00236         ResultType dispatch(ConcreteLhs* lhs, BaseRhs rhs)
00237             {
00238                 return (*getCallback(TypeInfo::create(rhs)))(*lhs, rhs);
00239             }
00240     };
00241 
00242 
00243     template<class ConcreteLhs,
00244              class BaseRhs,
00245              typename ResultType>
00246     class DoubleDispatcher<ConcreteLhs,
00247                    const SmartPtr<BaseRhs>&,
00248                    ResultType,
00249                    TypeTraits<NullType>::ConstReference>
00250                        : public DoubleDispatcherBase<BaseRhs,
00251                                      ResultType (*)(ConcreteLhs&, const SmartPtr<BaseRhs>&)>
00252     {
00253     public:
00254         DoubleDispatcher()
00255             : DoubleDispatcherBase<BaseRhs, ResultType (*)(ConcreteLhs&, const SmartPtr<BaseRhs>&)>()
00256             {
00257             }
00258         virtual ~DoubleDispatcher()
00259             {}
00260 
00261         template <typename ConcreteRhs,
00262             ResultType (ConcreteLhs::*callback)(const SmartPtr<ConcreteRhs>&)>
00263             void
00264             addMemberFunction()
00265             {
00266                 struct Local
00267                 {
00268                     static ResultType Trampoline(ConcreteLhs& lhs, const SmartPtr<BaseRhs>& rhs)
00269                         {
00270                             return ((lhs).*callback)(staticCast<ConcreteRhs>(rhs));
00271                         }
00272                 };
00273                 addCallback(TypeInfo::create<ConcreteRhs>(), &Local::Trampoline);
00274             }
00275 
00276         ResultType dispatch(ConcreteLhs& lhs, const SmartPtr<BaseRhs>& rhs)
00277             {
00278                 return (*getCallback(TypeInfo::create(*rhs)))(lhs, rhs);
00279             }
00280 
00281         ResultType dispatch(ConcreteLhs* lhs, const SmartPtr<BaseRhs>& rhs)
00282             {
00283                 return (*getCallback(TypeInfo::create(*rhs)))(*lhs, rhs);
00284             }
00285     };
00286 }
00287 
00288 #endif // NOT defined WNS_DOUBLEDISPATCHER_HPP
00289 
00290 

Generated on Wed May 23 03:31:34 2012 for openWNS by  doxygen 1.5.5