1 ////////////////////////////////////////////////////////////////////////////////
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_
18 // $Id: Visitor.h 751 2006-10-17 19:50:37Z syntheticpp $
21 /// \defgroup VisitorGroup Visitor
24 #include "HierarchyGenerators.h"
29 ////////////////////////////////////////////////////////////////////////////////
30 /// \class BaseVisitor
32 /// \ingroup VisitorGroup
33 /// The base class of any Acyclic Visitor
34 ////////////////////////////////////////////////////////////////////////////////
39 virtual ~BaseVisitor() {}
42 ////////////////////////////////////////////////////////////////////////////////
45 /// \ingroup VisitorGroup
46 /// The building block of Acyclic Visitor
50 /// Defining the visitable class:
53 /// class RasterBitmap : public BaseVisitable<>
56 /// LOKI_DEFINE_VISITABLE()
60 /// Way 1 to define a visitor:
62 /// class SomeVisitor :
63 /// public BaseVisitor // required
64 /// public Visitor<RasterBitmap>,
65 /// public Visitor<Paragraph>
68 /// void Visit(RasterBitmap&); // visit a RasterBitmap
69 /// void Visit(Paragraph &); // visit a Paragraph
73 /// Way 2 to define the visitor:
75 /// class SomeVisitor :
76 /// public BaseVisitor // required
77 /// public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
80 /// void Visit(RasterBitmap&); // visit a RasterBitmap
81 /// void Visit(Paragraph &); // visit a Paragraph
85 /// Way 3 to define the visitor:
87 /// class SomeVisitor :
88 /// public BaseVisitor // required
89 /// public Visitor<Seq<RasterBitmap, Paragraph>::Type>
92 /// void Visit(RasterBitmap&); // visit a RasterBitmap
93 /// void Visit(Paragraph &); // visit a Paragraph
97 /// \par Using const visit functions:
99 /// Defining the visitable class (true for const):
102 /// class RasterBitmap : public BaseVisitable<void, DefaultCatchAll, true>
105 /// LOKI_DEFINE_CONST_VISITABLE()
109 /// Defining the visitor which only calls const member functions:
111 /// class SomeVisitor :
112 /// public BaseVisitor // required
113 /// public Visitor<RasterBitmap, void, true>,
116 /// void Visit(const RasterBitmap&); // visit a RasterBitmap by a const member function
122 /// test/Visitor/main.cpp
123 ////////////////////////////////////////////////////////////////////////////////
125 template <class T, typename R = void, bool ConstVisit = false>
128 template <class T, typename R>
129 class Visitor<T, R, false>
132 typedef R ReturnType;
134 virtual ~Visitor() {}
135 virtual ReturnType Visit(ParamType &) = 0;
138 template <class T, typename R>
139 class Visitor<T, R, true>
142 typedef R ReturnType;
143 typedef const T ParamType;
144 virtual ~Visitor() {}
145 virtual ReturnType Visit(ParamType &) = 0;
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:
153 // class SomeVisitor :
154 // public BaseVisitor // required
155 // public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
158 // void Visit(RasterBitmap&); // visit a RasterBitmap
159 // void Visit(Paragraph &); // visit a Paragraph
161 ////////////////////////////////////////////////////////////////////////////////
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>
168 typedef R ReturnType;
169 // using Visitor<Head, R>::Visit;
170 // using Visitor<Tail, R>::Visit;
173 template <class Head, typename R>
174 class Visitor<Typelist<Head, NullType>, R, false> : public Visitor<Head, R, false>
177 typedef R ReturnType;
178 using Visitor<Head, R, false>::Visit;
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>
186 typedef R ReturnType;
187 // using Visitor<Head, R>::Visit;
188 // using Visitor<Tail, R>::Visit;
191 template <class Head, typename R>
192 class Visitor<Typelist<Head, NullType>, R, true> : public Visitor<Head, R, true>
195 typedef R ReturnType;
196 using Visitor<Head, R, true>::Visit;
200 ////////////////////////////////////////////////////////////////////////////////
201 // class template BaseVisitorImpl
202 // Implements non-strict visitation (you can implement only part of the Visit
204 ////////////////////////////////////////////////////////////////////////////////
206 template <class TList, typename R = void> class BaseVisitorImpl;
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>
214 // using BaseVisitorImpl<Tail, R>::Visit;
216 virtual R Visit(Head &)
222 template <class Head, typename R>
223 class BaseVisitorImpl<Typelist<Head, NullType>, R>
224 : public Visitor<Head, R>
227 virtual R Visit(Head &)
233 ////////////////////////////////////////////////////////////////////////////////
234 // class template BaseVisitable
235 ////////////////////////////////////////////////////////////////////////////////
237 template <typename R, typename Visited>
238 struct DefaultCatchAll
240 static R OnUnknownVisitor(Visited &, BaseVisitor &)
246 ////////////////////////////////////////////////////////////////////////////////
247 // class template BaseVisitable
248 ////////////////////////////////////////////////////////////////////////////////
253 template <typename, class> class CatchAll = DefaultCatchAll,
254 bool ConstVisitable = false
258 template<typename R,template <typename, class> class CatchAll>
259 class BaseVisitable<R, CatchAll, false>
262 typedef R ReturnType;
263 virtual ~BaseVisitable() {}
264 virtual ReturnType Accept(BaseVisitor &) = 0;
266 protected: // give access only to the hierarchy
268 static ReturnType AcceptImpl(T &visited, BaseVisitor &guest)
270 // Apply the Acyclic Visitor
271 if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
273 return p->Visit(visited);
275 return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
279 template<typename R,template <typename, class> class CatchAll>
280 class BaseVisitable<R, CatchAll, true>
283 typedef R ReturnType;
284 virtual ~BaseVisitable() {}
285 virtual ReturnType Accept(BaseVisitor &) const = 0;
287 protected: // give access only to the hierarchy
289 static ReturnType AcceptImpl(const T &visited, BaseVisitor &guest)
291 // Apply the Acyclic Visitor
292 if (Visitor<T,R,true>* p = dynamic_cast<Visitor<T,R,true>*>(&guest))
294 return p->Visit(visited);
296 return CatchAll<R, T>::OnUnknownVisitor(const_cast<T &>(visited), guest);
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 ////////////////////////////////////////////////////////////////////////////////
308 #define LOKI_DEFINE_VISITABLE() \
309 virtual ReturnType Accept(::Loki::BaseVisitor& guest) \
310 { return AcceptImpl(*this, guest); }
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 ////////////////////////////////////////////////////////////////////////////////
319 #define LOKI_DEFINE_CONST_VISITABLE() \
320 virtual ReturnType Accept(::Loki::BaseVisitor& guest) const \
321 { return AcceptImpl(*this, guest); }
323 ////////////////////////////////////////////////////////////////////////////////
324 /// \class CyclicVisitor
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 ////////////////////////////////////////////////////////////////////////////////
331 template <typename R, class TList>
332 class CyclicVisitor : public Visitor<TList, R>
335 typedef R ReturnType;
336 // using Visitor<TList, R>::Visit;
338 template <class Visited>
339 ReturnType GenericVisit(Visited &host)
341 Visitor<Visited, ReturnType>& subObj = *this;
342 return subObj.Visit(host);
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 ////////////////////////////////////////////////////////////////////////////////
352 #define LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
353 virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
354 { return guest.GenericVisit(*this); }
360 #endif // end file guardian