00001 #ifndef OPENTISSUE_UTILITY_DISPATCHERS_DISPATCHERS_DYNAMIC_TABLE_DISPATCHER_H
00002 #define OPENTISSUE_UTILITY_DISPATCHERS_DISPATCHERS_DYNAMIC_TABLE_DISPATCHER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/utility/dispatchers/dispatchers_unbound_dispatch_function.h>
00013 #include <boost/multi_array.hpp>
00014 #include <boost/shared_ptr.hpp>
00015
00016 namespace OpenTissue
00017 {
00018 namespace utility
00019 {
00020 namespace dispatchers
00021 {
00022
00043 template <
00044 class Base
00045 , bool Mirrored = false
00046 , typename R = void
00047 , typename T3 = void
00048 >
00049 class DynamicTableDispatcher
00050 {
00051 private:
00052
00055 class FunctorBase
00056 {
00057 public:
00058
00061 virtual ~FunctorBase(){}
00062
00077 virtual R operator()(Base& t1, Base& t2, T3& t3) const = 0;
00078 };
00079
00090 template < class T1, class T2, bool Swap = false >
00091 class Functor
00092 : public FunctorBase
00093 {
00094 private:
00095
00096 typedef R FuncType(T1&, T2&, T3&);
00097
00098 FuncType* const m_func;
00099
00100 public:
00101
00107 Functor(FuncType* func)
00108 : m_func(func)
00109 {}
00110
00111 R operator()(Base& t1, Base& t2, T3& t3) const
00112 {
00113
00114
00115 if (Swap)
00116 {
00117 return m_func(static_cast<T1&>(t2), static_cast<T2&>(t1), t3);
00118 }
00119 else
00120 {
00121 return m_func(static_cast<T1&>(t1), static_cast<T2&>(t2), t3);
00122 }
00123 }
00124 };
00125
00126 private:
00127
00128 typedef boost::shared_ptr<FunctorBase> FunctorPtr;
00129 typedef boost::multi_array<FunctorPtr, 2> FunctorTableType;
00130
00131 FunctorTableType m_functor_table;
00132
00133 public:
00134
00135 DynamicTableDispatcher()
00136 : m_functor_table( boost::extents[0][0])
00137 {}
00138
00152 template < class T1, class T2 >
00153 void bind(R (*f)(T1&, T2&, T3&))
00154 {
00155 using std::max;
00156
00157 boost::multi_array_types::index idx1 = T1::id();
00158 boost::multi_array_types::index idx2 = T2::id();
00159
00160
00161 boost::multi_array_types::size_type max_idx = max(idx1, idx2);
00162
00163 if (max_idx >= m_functor_table.shape()[0])
00164 {
00165 m_functor_table.resize(boost::extents[max_idx+1][max_idx+1]);
00166 }
00167
00168
00169
00170 if (Mirrored)
00171 {
00172 m_functor_table[idx2][idx1].reset(new Functor<T1,T2,true>(f));
00173 }
00174
00175 m_functor_table[idx1][idx2].reset(new Functor<T1,T2,false>(f));
00176 }
00177
00192 R operator()(Base& t1, Base& t2, T3& t3)
00193 {
00194 using std::max;
00195
00196 boost::multi_array_types::index idx1 = t1.class_id();
00197 boost::multi_array_types::index idx2 = t2.class_id();
00198
00199 boost::multi_array_types::size_type max_idx = max(idx1, idx2);
00200
00201
00202 if (max_idx >= m_functor_table.shape()[0])
00203 throw UnboundDispatchFunction();
00204
00205 FunctorPtr f = m_functor_table[idx1][idx2];
00206
00207
00208 if (f.get()==0)
00209 throw UnboundDispatchFunction();
00210
00211 return f->operator()(t1, t2, t3);
00212 }
00213 };
00214
00215
00216
00217
00220 template < class Base, bool Mirrored, typename R >
00221 class DynamicTableDispatcher<Base, Mirrored, R, void>
00222 {
00223 private:
00224
00227 class FunctorBase
00228 {
00229 public:
00230
00233 virtual ~FunctorBase(){}
00234
00248 virtual R operator()(Base& t1, Base& t2) const = 0;
00249
00250 };
00251
00262 template < class T1, class T2, bool Swap = false >
00263 class Functor
00264 : public FunctorBase
00265 {
00266 private:
00267
00268 typedef R FuncType(T1&, T2&);
00269
00270 FuncType* const m_func;
00271
00272 public:
00273
00279 Functor(FuncType* func)
00280 : m_func(func)
00281 {}
00282
00285 R operator()(Base& t1, Base& t2) const
00286 {
00287
00288
00289 if (Swap)
00290 {
00291 return m_func(static_cast<T1&>(t2), static_cast<T2&>(t1));
00292 }
00293 else
00294 {
00295 return m_func(static_cast<T1&>(t1), static_cast<T2&>(t2));
00296 }
00297 }
00298 };
00299
00300 private:
00301
00302 typedef boost::shared_ptr<FunctorBase> FunctorPtr;
00303 typedef boost::multi_array<FunctorPtr, 2> FunctorTableType;
00304
00305 FunctorTableType m_functor_table;
00306
00307 public:
00308
00311 DynamicTableDispatcher()
00312 : m_functor_table(boost::extents[0][0])
00313 {}
00314
00328 template < class T1, class T2 >
00329 void bind(R (*f)(T1&, T2&))
00330 {
00331 using std::max;
00332
00333 boost::multi_array_types::index idx1 = T1::id();
00334 boost::multi_array_types::index idx2 = T2::id();
00335
00336
00337 boost::multi_array_types::size_type max_idx = max(idx1, idx2);
00338
00339 if (max_idx >= m_functor_table.shape()[0])
00340 {
00341 m_functor_table.resize(boost::extents[max_idx+1][max_idx+1]);
00342 }
00343
00344
00345
00346 if (Mirrored)
00347 {
00348 m_functor_table[idx2][idx1].reset(new Functor<T1,T2,true>(f));
00349 }
00350 m_functor_table[idx1][idx2].reset(new Functor<T1,T2,false>(f));
00351 }
00352
00364 R operator()(Base& t1, Base& t2)
00365 {
00366 using std::max;
00367
00368 boost::multi_array_types::index idx1 = t1.class_id();
00369 boost::multi_array_types::index idx2 = t2.class_id();
00370
00371 boost::multi_array_types::size_type max_idx = max(idx1, idx2);
00372
00373
00374 if (max_idx >= m_functor_table.shape()[0])
00375 throw UnboundDispatchFunction();
00376
00377 FunctorPtr f = m_functor_table[idx1][idx2];
00378
00379
00380 if (f.get()==0)
00381 throw UnboundDispatchFunction();
00382
00383 return f->operator()(t1, t2);
00384 }
00385 };
00386
00387 }
00388 }
00389 }
00390
00391
00392 #endif
00393