FnDispatcher.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #ifndef SOFA_HELPER_FNDISPATCHER_H
00028 #define SOFA_HELPER_FNDISPATCHER_H
00029 
00030 #include <map>
00031 #include <typeinfo>
00032 
00033 namespace sofa
00034 {
00035 
00036 namespace helper
00037 {
00038 
00039 class TypeInfo
00040 {
00041 public:
00042     const std::type_info* pt;
00043     TypeInfo(const std::type_info& t) : pt(&t) { }
00044     operator const std::type_info&() const { return *pt; }
00045     bool operator==(const TypeInfo& t) const { return *pt == *t.pt; }
00046     bool operator!=(const TypeInfo& t) const { return *pt != *t.pt; }
00047 #ifdef _MSC_VER
00048     bool operator<(const TypeInfo& t) const { return (pt->before(*t.pt)!=0); }
00049 #else
00050     bool operator<(const TypeInfo& t) const { return pt->before(*t.pt); }
00051 #endif
00052 };
00053 
00054 template <class BaseClass, typename ResulT = void>
00055 class BasicDispatcher
00056 {
00057 public:
00058     typedef ResulT (*F)(BaseClass &,BaseClass &);
00059     
00060 protected:
00061     typedef std::pair<TypeInfo,TypeInfo> KeyType;
00062     typedef std::map<KeyType, F> MapType;
00063     MapType callBackMap;
00064         virtual ~BasicDispatcher(){}
00065 public:
00066     void add(const std::type_info& class1, const std::type_info& class2, F fun)
00067     {
00068         callBackMap[KeyType(class1,class2)] = fun;
00069     }
00070 
00071     void ignore(const std::type_info& class1, const std::type_info& class2)
00072     {
00073         callBackMap[KeyType(class1,class2)] = ignoreFn;
00074     }
00075     
00076     template <class ConcreteClass1,class ConcreteClass2,ResulT (*F)(ConcreteClass1&,ConcreteClass2&), bool symetric>
00077     void ignore()
00078     {
00079         this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass1), typeid(ConcreteClass2), &ignoreFn);
00080         if (symetric)
00081         {
00082             this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass2), typeid(ConcreteClass1), &ignoreFn);
00083         }
00084     }
00085     
00086     virtual ResulT defaultFn(BaseClass& arg1, BaseClass& arg2);
00087     static ResulT ignoreFn(BaseClass& arg1, BaseClass& arg2);
00088     ResulT go(BaseClass &arg1,BaseClass &arg2);
00090     bool isSupported(BaseClass &arg1, BaseClass &arg2);
00091 };
00092 
00093 template <class BaseClass, typename ResulT>
00094 class FnDispatcher : public BasicDispatcher<BaseClass, ResulT>
00095 {
00096 public:
00097     
00098     template <class ConcreteClass1, class ConcreteClass2,ResulT (*F)(ConcreteClass1&,ConcreteClass2&), bool symetric>
00099     void add()
00100     {
00101         struct Local
00102         {
00103         static ResulT trampoline(BaseClass &arg1,BaseClass &arg2)
00104         {
00105             return F(static_cast<ConcreteClass1 &> (arg1),
00106                     static_cast<ConcreteClass2 &> (arg2));
00107         }
00108         static ResulT trampolineR(BaseClass &arg1,BaseClass &arg2)
00109         {
00110             return trampoline (arg2, arg1);
00111         }
00112         };
00113         this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass1), typeid(ConcreteClass2), &Local::trampoline);
00114         if (symetric)
00115         {
00116             this->BasicDispatcher<BaseClass, ResulT>::add(typeid(ConcreteClass2), typeid(ConcreteClass1), &Local::trampolineR);
00117         }
00118     }
00119     
00120     template <class ConcreteClass1, class ConcreteClass2, bool symetric>
00121     void ignore()
00122     {
00123         this->BasicDispatcher<BaseClass, ResulT>::ignore(typeid(ConcreteClass1), typeid(ConcreteClass2));
00124         if (symetric)
00125         {
00126             this->BasicDispatcher<BaseClass, ResulT>::ignore(typeid(ConcreteClass2), typeid(ConcreteClass1));
00127         }
00128     }
00129 };
00130 
00131 
00132 template <class BaseClass, typename ResulT>
00133 class SingletonFnDispatcher : public FnDispatcher<BaseClass, ResulT>
00134 {
00135 protected:
00136     SingletonFnDispatcher();
00137 public:
00138     static SingletonFnDispatcher<BaseClass, ResulT>* getInstance();
00139     /*
00140     template <class ConcreteClass1,class ConcreteClass2,ResulT (*F)(ConcreteClass1&,ConcreteClass2&), bool symetric>
00141     static void Add()
00142     {
00143         getInstance()->add<ConcreteClass1,ConcreteClass2,F,symetric>();
00144     }
00145     
00146     template <class ConcreteClass1, class ConcreteClass2, bool symetric>
00147     static void Ignore()
00148     {
00149         getInstance()->ignore<ConcreteClass1,ConcreteClass2,symetric>();
00150     }
00151     
00152     static ResulT Go(BaseClass &arg1,BaseClass &arg2)
00153     {
00154         getInstance()->go(arg1,arg2);
00155     }
00156     */
00157 };
00158 
00159 } // namespace helper
00160 
00161 } // namespace sofa
00162 
00163 #endif

Generated on Sun Nov 23 02:29:29 2008 for Sofa by  doxygen 1.5.7.1