]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/Visitor.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / Visitor.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 //     purpose is hereby granted without fee, provided that the above copyright
9 //     notice appear in all copies and that both that copyright notice and this
10 //     permission notice appear in supporting documentation.
11 // The author or Addison-Wesley Longman make no representations about the
12 //     suitability of this software for any purpose. It is provided "as is"
13 //     without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_VISITOR_INC_
16 #define LOKI_VISITOR_INC_
17
18 // $Id: Visitor.h 751 2006-10-17 19:50:37Z syntheticpp $
19
20
21 ///  \defgroup VisitorGroup Visitor
22
23 #include "Typelist.h"
24 #include "HierarchyGenerators.h"
25
26 namespace Loki
27 {
28
29 ////////////////////////////////////////////////////////////////////////////////
30 /// \class BaseVisitor
31 ///
32 /// \ingroup VisitorGroup
33 /// The base class of any Acyclic Visitor
34 ////////////////////////////////////////////////////////////////////////////////
35
36 class BaseVisitor
37 {
38 public:
39         virtual ~BaseVisitor() {}
40 };
41
42 ////////////////////////////////////////////////////////////////////////////////
43 /// \class Visitor
44 ///
45 /// \ingroup VisitorGroup
46 /// The building block of Acyclic Visitor
47 ///
48 /// \par Usage
49 ///
50 /// Defining the visitable class:
51 ///
52 /// \code
53 /// class RasterBitmap : public BaseVisitable<>
54 /// {
55 /// public:
56 ///     LOKI_DEFINE_VISITABLE()
57 /// };
58 /// \endcode
59 ///
60 /// Way 1 to define a visitor:
61 /// \code
62 /// class SomeVisitor :
63 ///     public BaseVisitor // required
64 ///     public Visitor<RasterBitmap>,
65 ///     public Visitor<Paragraph>
66 /// {
67 /// public:
68 ///     void Visit(RasterBitmap&); // visit a RasterBitmap
69 ///     void Visit(Paragraph &);   // visit a Paragraph
70 /// };
71 /// \endcode
72 ///
73 /// Way 2 to define the visitor:
74 /// \code
75 /// class SomeVisitor :
76 ///     public BaseVisitor // required
77 ///     public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
78 /// {
79 /// public:
80 ///     void Visit(RasterBitmap&); // visit a RasterBitmap
81 ///     void Visit(Paragraph &);   // visit a Paragraph
82 /// };
83 /// \endcode
84 ///
85 /// Way 3 to define the visitor:
86 /// \code
87 /// class SomeVisitor :
88 ///     public BaseVisitor // required
89 ///     public Visitor<Seq<RasterBitmap, Paragraph>::Type>
90 /// {
91 /// public:
92 ///     void Visit(RasterBitmap&); // visit a RasterBitmap
93 ///     void Visit(Paragraph &);   // visit a Paragraph
94 /// };
95 /// \endcode
96 ///
97 /// \par Using const visit functions:
98 ///
99 /// Defining the visitable class (true for const):
100 ///
101 /// \code
102 /// class RasterBitmap : public BaseVisitable<void, DefaultCatchAll, true>
103 /// {
104 /// public:
105 ///     LOKI_DEFINE_CONST_VISITABLE()
106 /// };
107 /// \endcode
108 ///
109 /// Defining the visitor which only calls const member functions:
110 /// \code
111 /// class SomeVisitor :
112 ///     public BaseVisitor // required
113 ///     public Visitor<RasterBitmap, void, true>,
114 /// {
115 /// public:
116 ///     void Visit(const RasterBitmap&); // visit a RasterBitmap by a const member function
117 /// };
118 /// \endcode
119 ///
120 /// \par Example:
121 ///
122 /// test/Visitor/main.cpp
123 ////////////////////////////////////////////////////////////////////////////////
124
125 template <class T, typename R = void, bool ConstVisit = false>
126 class Visitor;
127
128 template <class T, typename R>
129 class Visitor<T, R, false>
130 {
131 public:
132         typedef R ReturnType;
133         typedef T ParamType;
134         virtual ~Visitor() {}
135         virtual ReturnType Visit(ParamType &) = 0;
136 };
137
138 template <class T, typename R>
139 class Visitor<T, R, true>
140 {
141 public:
142         typedef R ReturnType;
143         typedef const T ParamType;
144         virtual ~Visitor() {}
145         virtual ReturnType Visit(ParamType &) = 0;
146 };
147
148 ////////////////////////////////////////////////////////////////////////////////
149 // class template Visitor (specialization)
150 // This specialization is not present in the book. It makes it easier to define
151 // Visitors for multiple types in a shot by using a typelist. Example:
152 //
153 // class SomeVisitor :
154 //     public BaseVisitor // required
155 //     public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
156 // {
157 // public:
158 //     void Visit(RasterBitmap&); // visit a RasterBitmap
159 //     void Visit(Paragraph &);   // visit a Paragraph
160 // };
161 ////////////////////////////////////////////////////////////////////////////////
162
163 template <class Head, class Tail, typename R>
164 class Visitor<Typelist<Head, Tail>, R, false>
165         : public Visitor<Head, R, false>, public Visitor<Tail, R, false>
166 {
167 public:
168         typedef R ReturnType;
169         // using Visitor<Head, R>::Visit;
170         // using Visitor<Tail, R>::Visit;
171 };
172
173 template <class Head, typename R>
174 class Visitor<Typelist<Head, NullType>, R, false> : public Visitor<Head, R, false>
175 {
176 public:
177         typedef R ReturnType;
178         using Visitor<Head, R, false>::Visit;
179 };
180
181 template <class Head, class Tail, typename R>
182 class Visitor<Typelist<Head, Tail>, R, true>
183         : public Visitor<Head, R, true>, public Visitor<Tail, R, true>
184 {
185 public:
186         typedef R ReturnType;
187         // using Visitor<Head, R>::Visit;
188         // using Visitor<Tail, R>::Visit;
189 };
190
191 template <class Head, typename R>
192 class Visitor<Typelist<Head, NullType>, R, true> : public Visitor<Head, R, true>
193 {
194 public:
195         typedef R ReturnType;
196         using Visitor<Head, R, true>::Visit;
197 };
198
199
200 ////////////////////////////////////////////////////////////////////////////////
201 // class template BaseVisitorImpl
202 // Implements non-strict visitation (you can implement only part of the Visit
203 //     functions)
204 ////////////////////////////////////////////////////////////////////////////////
205
206 template <class TList, typename R = void> class BaseVisitorImpl;
207
208 template <class Head, class Tail, typename R>
209 class BaseVisitorImpl<Typelist<Head, Tail>, R>
210         : public Visitor<Head, R>
211         , public BaseVisitorImpl<Tail, R>
212 {
213 public:
214         // using BaseVisitorImpl<Tail, R>::Visit;
215
216         virtual R Visit(Head &)
217         {
218                 return R();
219         }
220 };
221
222 template <class Head, typename R>
223 class BaseVisitorImpl<Typelist<Head, NullType>, R>
224         : public Visitor<Head, R>
225 {
226 public:
227         virtual R Visit(Head &)
228         {
229                 return R();
230         }
231 };
232
233 ////////////////////////////////////////////////////////////////////////////////
234 // class template BaseVisitable
235 ////////////////////////////////////////////////////////////////////////////////
236
237 template <typename R, typename Visited>
238 struct DefaultCatchAll
239 {
240         static R OnUnknownVisitor(Visited &, BaseVisitor &)
241         {
242                 return R();
243         }
244 };
245
246 ////////////////////////////////////////////////////////////////////////////////
247 // class template BaseVisitable
248 ////////////////////////////////////////////////////////////////////////////////
249
250 template
251 <
252 typename R = void,
253          template <typename, class> class CatchAll = DefaultCatchAll,
254          bool ConstVisitable = false
255          >
256 class BaseVisitable;
257
258 template<typename R,template <typename, class> class CatchAll>
259 class BaseVisitable<R, CatchAll, false>
260 {
261 public:
262         typedef R ReturnType;
263         virtual ~BaseVisitable() {}
264         virtual ReturnType Accept(BaseVisitor &) = 0;
265
266 protected: // give access only to the hierarchy
267         template <class T>
268         static ReturnType AcceptImpl(T &visited, BaseVisitor &guest)
269         {
270                 // Apply the Acyclic Visitor
271                 if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
272                 {
273                         return p->Visit(visited);
274                 }
275                 return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
276         }
277 };
278
279 template<typename R,template <typename, class> class CatchAll>
280 class BaseVisitable<R, CatchAll, true>
281 {
282 public:
283         typedef R ReturnType;
284         virtual ~BaseVisitable() {}
285         virtual ReturnType Accept(BaseVisitor &) const = 0;
286
287 protected: // give access only to the hierarchy
288         template <class T>
289         static ReturnType AcceptImpl(const T &visited, BaseVisitor &guest)
290         {
291                 // Apply the Acyclic Visitor
292                 if (Visitor<T,R,true>* p = dynamic_cast<Visitor<T,R,true>*>(&guest))
293                 {
294                         return p->Visit(visited);
295                 }
296                 return CatchAll<R, T>::OnUnknownVisitor(const_cast<T &>(visited), guest);
297         }
298 };
299
300
301 ////////////////////////////////////////////////////////////////////////////////
302 /// \def LOKI_DEFINE_VISITABLE()
303 /// \ingroup VisitorGroup
304 /// Put it in every class that you want to make visitable
305 /// (in addition to deriving it from BaseVisitable<R>)
306 ////////////////////////////////////////////////////////////////////////////////
307
308 #define LOKI_DEFINE_VISITABLE() \
309     virtual ReturnType Accept(::Loki::BaseVisitor& guest) \
310     { return AcceptImpl(*this, guest); }
311
312 ////////////////////////////////////////////////////////////////////////////////
313 /// \def LOKI_DEFINE_CONST_VISITABLE()
314 /// \ingroup VisitorGroup
315 /// Put it in every class that you want to make visitable by const member
316 /// functions (in addition to deriving it from BaseVisitable<R>)
317 ////////////////////////////////////////////////////////////////////////////////
318
319 #define LOKI_DEFINE_CONST_VISITABLE() \
320     virtual ReturnType Accept(::Loki::BaseVisitor& guest) const \
321     { return AcceptImpl(*this, guest); }
322
323 ////////////////////////////////////////////////////////////////////////////////
324 /// \class CyclicVisitor
325 ///
326 /// \ingroup VisitorGroup
327 /// Put it in every class that you want to make visitable (in addition to
328 /// deriving it from BaseVisitable<R>
329 ////////////////////////////////////////////////////////////////////////////////
330
331 template <typename R, class TList>
332 class CyclicVisitor : public Visitor<TList, R>
333 {
334 public:
335         typedef R ReturnType;
336         // using Visitor<TList, R>::Visit;
337
338         template <class Visited>
339         ReturnType GenericVisit(Visited &host)
340         {
341                 Visitor<Visited, ReturnType>& subObj = *this;
342                 return subObj.Visit(host);
343         }
344 };
345
346 ////////////////////////////////////////////////////////////////////////////////
347 /// \def LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor)
348 /// \ingroup VisitorGroup
349 /// Put it in every class that you want to make visitable by a cyclic visitor
350 ////////////////////////////////////////////////////////////////////////////////
351
352 #define LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
353     virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
354     { return guest.GenericVisit(*this); }
355
356 } // namespace Loki
357
358
359
360 #endif // end file guardian
361