Program listing for file kernel/src/utils/SiconosTools/VisitorMaker.hpp#

  1#ifndef VisitorMaker_hpp
  2#define VisitorMaker_hpp
  3
  4#include <SiconosVisitor.hpp>
  5#include <boost/type_traits.hpp>
  6#include <boost/mpl/if.hpp>
  7#include <boost/mpl/vector.hpp>
  8#include <boost/mpl/fold.hpp>
  9
 10
 11
 12
 13namespace Experimental {
 14
 15  struct TypeNotFound {};
 16
 17
 18  template<typename T, typename Action, typename BaseType>
 19  struct Call : public Action
 20  {
 21    typedef Call<T, Action, BaseType> type;
 22
 23    using Action::visit;
 24
 25    virtual void visit(const T& x)
 26    {
 27      (*this)(static_cast<const BaseType&>(x));
 28    }
 29  };
 30
 31
 32  template<typename T, typename Action>
 33  struct Call<T, Action, TypeNotFound> : public Action
 34  {
 35    typedef Call<T, Action, TypeNotFound> type;
 36
 37    using Action::visit;
 38
 39    virtual void visit(const T& x)
 40    {
 41    }
 42  };
 43
 44
 45  template<typename T, typename Pred>
 46  class VisitMaker
 47  {
 48  private:
 49    typedef typename
 50    boost::mpl::fold<
 51    typename Pred::Action::Base,
 52    TypeNotFound,
 53    boost::mpl::if_<boost::is_base_of<boost::mpl::_2, T>,
 54                    boost::mpl::_2,
 55                    boost::mpl::_1> >::type BaseType;
 56
 57  public:
 58
 59    typedef typename Call<T, typename Pred::Action, BaseType>::type Action;
 60  };
 61
 62
 63#undef REGISTER
 64#undef REGISTER_STRUCT
 65#undef REGISTER_BASE
 66#undef REGISTER_BASE_EXTERN
 67
 68#define REGISTER(X) VisitMaker<X,
 69#define REGISTER_STRUCT(X)
 70#define REGISTER_BASE(X, Y) REGISTER(X)
 71#define REGISTER_BASE_EXTERN(X, Y)
 72
 73  template<typename T>
 74  struct GlobalVisitor
 75  {
 76    typedef typename
 77    VISITOR_CLASSES()
 78    T
 79
 80#undef REGISTER
 81#undef REGISTER_STRUCT
 82#undef REGISTER_BASE
 83#undef REGISTER_BASE_EXTERN
 84
 85#define REGISTER(X) >
 86#define REGISTER_STRUCT(X)
 87#define REGISTER_BASE(X, Y) REGISTER(X)
 88#define REGISTER_BASE_EXTERN(X, Y)
 89    VISITOR_CLASSES()
 90      ::Action Make;
 91  };
 92
 93
 94
 95  struct empty{};
 96
 97  template<typename T1 = empty, typename T2 = empty, typename T3 = empty,
 98           typename T4 = empty, typename T5 = empty, typename T6 = empty,
 99           typename T7 = empty, typename T8 = empty, typename T9 = empty>
100  struct Classes
101  {
102    typedef typename boost::mpl::vector<T1, T2, T3, T4, T5, T6, T7, T8, T9> Base;
103  };
104
105  template<typename T1>
106  struct Classes<T1, empty, empty, empty, empty, empty, empty, empty, empty>
107  {
108    typedef typename boost::mpl::vector<T1> Base;
109  };
110
111  template<typename T1, typename T2>
112  struct Classes<T1, T2, empty, empty, empty, empty, empty, empty, empty>
113  {
114    typedef typename boost::mpl::vector<T1, T2> Base;
115  };
116
117  template<typename T1, typename T2, typename T3>
118  struct Classes<T1, T2, T3, empty, empty, empty, empty, empty, empty>
119  {
120    typedef typename boost::mpl::vector<T1, T2, T3> Base;
121  };
122
123  template<typename T1, typename T2, typename T3, typename T4>
124  struct Classes<T1, T2, T3, T4, empty, empty, empty, empty, empty>
125  {
126    typedef typename boost::mpl::vector<T1, T2, T3, T4> Base;
127  };
128
129  template<typename T1, typename T2, typename T3, typename T4, typename T5>
130  struct Classes<T1, T2, T3, T4, T5, empty, empty, empty, empty>
131{
132  typedef typename boost::mpl::vector<T1, T2, T3, T4, T5> Base;
133  };
134
135  template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
136  struct Classes<T1, T2, T3, T4, T5, T6, empty, empty, empty>
137  {
138    typedef typename boost::mpl::vector<T1, T2, T3, T4, T5, T6> Base;
139  };
140
141  template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
142  struct Classes<T1, T2, T3, T4, T5, T6, T7, empty, empty>
143  {
144    typedef typename boost::mpl::vector<T1, T2, T3, T4, T5, T6, T7> Base;
145  };
146
147  template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
148  struct Classes<T1, T2, T3, T4, T5, T6, T7, T8, empty>
149  {
150    typedef typename boost::mpl::vector<T1, T2, T3, T4, T5, T6, T7, T8> Base;
151  };
152
153
154  template<typename C, typename T>
155  struct Filter
156  {
157    struct _T : public T, public C
158    {
159      typedef _T Action;
160    };
161
162    typedef typename
163    boost::mpl::fold<
164      typename C::Base,
165      _T,
166      VisitMaker<boost::mpl::_2, boost::mpl::_1 >
167      >::type Make;
168  };
169
170  template<typename C, typename T>
171  struct Visitor
172  {
173    typedef typename Filter<C, T>::Make LocalFilter;
174
175    typedef typename GlobalVisitor<LocalFilter>::Make Make;
176
177  };
178
179}
180
181#endif