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-Welsey 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 
 16 // Last update: June 20, 2001
 17 
 18 #ifndef VISITOR_INC_
 19 #define VISITOR_INC_
 20 
 21 #include "Typelist.h"
 22 #include "HierarchyGenerators.h"
 23 
 24 namespace Loki
 25 {
 26 
 27 ////////////////////////////////////////////////////////////////////////////////
 28 // class template BaseVisitor
 29 // The base class of any Acyclic Visitor
 30 ////////////////////////////////////////////////////////////////////////////////
 31 
 32     class BaseVisitor
 33     {
 34     public:
 35         virtual ~BaseVisitor() {}
 36     };
 37     
 38 ////////////////////////////////////////////////////////////////////////////////
 39 // class template Visitor
 40 // The building block of Acyclic Visitor
 41 ////////////////////////////////////////////////////////////////////////////////
 42 
 43     template <class T, typename R = void>
 44     class Visitor
 45     {
 46     public:
 47         typedef R ReturnType;
 48         virtual ReturnType Visit(T&) = 0;
 49     };
 50     
 51 ////////////////////////////////////////////////////////////////////////////////
 52 // class template Visitor (specialization)
 53 // This specialization is not present in the book. It makes it easier to define
 54 // Visitors for multiple types in a shot by using a typelist. Example:
 55 //
 56 // class SomeVisitor : 
 57 //     public BaseVisitor // required
 58 //     public Visitor<TYPELIST_2(RasterBitmap, Paragraph)>, 
 59 //     public Visitor<Paragraph>
 60 // {
 61 // public:
 62 //     void Visit(RasterBitmap&); // visit a RasterBitmap
 63 //     void Visit(Paragraph &);   // visit a Paragraph
 64 // };
 65 ////////////////////////////////////////////////////////////////////////////////
 66 
 67     template <class Head, class Tail, typename R>
 68     class Visitor<Typelist<Head, Tail>, R>
 69         : public Visitor<Head, R>, public Visitor<Tail, R>
 70     {
 71     public:
 72         typedef R ReturnType;
 73        // using Visitor<Head, R>::Visit;
 74        // using Visitor<Tail, R>::Visit;
 75     };
 76     
 77     template <class Head, typename R>
 78     class Visitor<Typelist<Head, NullType>, R> : public Visitor<Head, R>
 79     {
 80     public:
 81         typedef R ReturnType;
 82         using Visitor<Head, R>::Visit;
 83     };
 84 
 85 ////////////////////////////////////////////////////////////////////////////////
 86 // class template BaseVisitorImpl
 87 // Implements non-strict visitation (you can implement only part of the Visit
 88 //     functions)
 89 ////////////////////////////////////////////////////////////////////////////////
 90 
 91     template <class TList, typename R = void> class BaseVisitorImpl;
 92 
 93     template <class Head, class Tail, typename R>
 94     class BaseVisitorImpl<Typelist<Head, Tail>, R>
 95         : public Visitor<Head, R>
 96         , public BaseVisitorImpl<Tail, R>
 97     {
 98     public:
 99        // using BaseVisitorImpl<Tail, R>::Visit;
100 
101         virtual R Visit(Head&)
102         { return R(); }
103     };
104     
105     template <class Head, typename R>
106     class BaseVisitorImpl<Typelist<Head, NullType>, R>
107         : public Visitor<Head, R>
108     {
109     public:
110         virtual R Visit(Head&)
111         { return R(); }
112     };
113     
114 ////////////////////////////////////////////////////////////////////////////////
115 // class template BaseVisitable
116 ////////////////////////////////////////////////////////////////////////////////
117 
118 template <typename R, typename Visited>
119 struct DefaultCatchAll
120 {
121     static R OnUnknownVisitor(Visited&, BaseVisitor&)
122     { return R(); }
123 };
124 
125 ////////////////////////////////////////////////////////////////////////////////
126 // class template BaseVisitable
127 ////////////////////////////////////////////////////////////////////////////////
128 
129     template 
130     <
131         typename R = void, 
132         template <typename, class> class CatchAll = DefaultCatchAll
133     >
134     class BaseVisitable
135     {
136     public:
137         typedef R ReturnType;
138         virtual ~BaseVisitable() {}
139         virtual ReturnType Accept(BaseVisitor&) = 0;
140         
141     protected: // give access only to the hierarchy
142         template <class T>
143         static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
144         {
145             // Apply the Acyclic Visitor
146             if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
147             {
148                 return p->Visit(visited);
149             }
150             return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
151         }
152     };
153 
154 ////////////////////////////////////////////////////////////////////////////////
155 // macro DEFINE_VISITABLE
156 // Put it in every class that you want to make visitable (in addition to 
157 //     deriving it from BaseVisitable<R>
158 ////////////////////////////////////////////////////////////////////////////////
159 
160 #define DEFINE_VISITABLE() \
161     virtual ReturnType Accept(BaseVisitor& guest) \
162     { return AcceptImpl(*this, guest); }
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 // class template CyclicVisitor
166 // Put it in every class that you want to make visitable (in addition to 
167 //     deriving it from BaseVisitable<R>
168 ////////////////////////////////////////////////////////////////////////////////
169 
170     template <typename R, class TList>
171     class CyclicVisitor : public Visitor<TList, R>
172     {
173     public:
174         typedef R ReturnType;
175         // using Visitor<TList, R>::Visit;
176         
177         template <class Visited>
178         ReturnType GenericVisit(Visited& host)
179         {
180             Visitor<Visited, ReturnType>& subObj = *this;
181             return subObj.Visit(host);
182         }
183     };
184     
185 ////////////////////////////////////////////////////////////////////////////////
186 // macro DEFINE_CYCLIC_VISITABLE
187 // Put it in every class that you want to make visitable by a cyclic visitor
188 ////////////////////////////////////////////////////////////////////////////////
189 
190 #define DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
191     virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
192     { return guest.GenericVisit(*this); }
193 
194 } // namespace Loki
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 // Change log:
198 // March 20: add default argument DefaultCatchAll to BaseVisitable
199 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
200 ////////////////////////////////////////////////////////////////////////////////
201 
202 #endif // VISITOR_INC_
posted @ 2012-10-31 15:29  crazylhf  阅读(117)  评论(0)    收藏  举报