![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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
1.5.5