Visitor.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Wesley Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_VISITOR_INC_
00016 #define LOKI_VISITOR_INC_
00017 
00018 // $Id: Visitor.h 751 2006-10-17 19:50:37Z syntheticpp $
00019 
00020 
00022 
00023 #include "Typelist.h"
00024 #include "HierarchyGenerators.h"
00025 
00026 namespace Loki
00027 {
00028 
00035 
00036     class BaseVisitor
00037     {
00038     public:
00039         virtual ~BaseVisitor() {}
00040     };
00041     
00124 
00125     template <class T, typename R = void, bool ConstVisit = false>
00126     class Visitor;
00127 
00128     template <class T, typename R>
00129     class Visitor<T, R, false>
00130     {
00131     public:
00132         typedef R ReturnType;
00133         typedef T ParamType;
00134         virtual ~Visitor() {}
00135         virtual ReturnType Visit(ParamType&) = 0;
00136     };
00137 
00138     template <class T, typename R>
00139     class Visitor<T, R, true>
00140     {
00141     public:
00142         typedef R ReturnType;
00143         typedef const T ParamType;
00144         virtual ~Visitor() {}
00145         virtual ReturnType Visit(ParamType&) = 0;
00146     };
00147 
00149 // class template Visitor (specialization)
00150 // This specialization is not present in the book. It makes it easier to define
00151 // Visitors for multiple types in a shot by using a typelist. Example:
00152 //
00153 // class SomeVisitor : 
00154 //     public BaseVisitor // required
00155 //     public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
00156 // {
00157 // public:
00158 //     void Visit(RasterBitmap&); // visit a RasterBitmap
00159 //     void Visit(Paragraph &);   // visit a Paragraph
00160 // };
00162 
00163     template <class Head, class Tail, typename R>
00164     class Visitor<Typelist<Head, Tail>, R, false>
00165         : public Visitor<Head, R, false>, public Visitor<Tail, R, false>
00166     {
00167     public:
00168         typedef R ReturnType;
00169        // using Visitor<Head, R>::Visit;
00170        // using Visitor<Tail, R>::Visit;
00171     };
00172     
00173     template <class Head, typename R>
00174     class Visitor<Typelist<Head, NullType>, R, false> : public Visitor<Head, R, false>
00175     {
00176     public:
00177         typedef R ReturnType;
00178         using Visitor<Head, R, false>::Visit;
00179     };
00180 
00181     template <class Head, class Tail, typename R>
00182     class Visitor<Typelist<Head, Tail>, R, true>
00183         : public Visitor<Head, R, true>, public Visitor<Tail, R, true>
00184     {
00185     public:
00186         typedef R ReturnType;
00187        // using Visitor<Head, R>::Visit;
00188        // using Visitor<Tail, R>::Visit;
00189     };
00190     
00191     template <class Head, typename R>
00192     class Visitor<Typelist<Head, NullType>, R, true> : public Visitor<Head, R, true>
00193     {
00194     public:
00195         typedef R ReturnType;
00196         using Visitor<Head, R, true>::Visit;
00197     };
00198 
00199 
00201 // class template BaseVisitorImpl
00202 // Implements non-strict visitation (you can implement only part of the Visit
00203 //     functions)
00205 
00206     template <class TList, typename R = void> class BaseVisitorImpl;
00207 
00208     template <class Head, class Tail, typename R>
00209     class BaseVisitorImpl<Typelist<Head, Tail>, R>
00210         : public Visitor<Head, R>
00211         , public BaseVisitorImpl<Tail, R>
00212     {
00213     public:
00214        // using BaseVisitorImpl<Tail, R>::Visit;
00215 
00216         virtual R Visit(Head&)
00217         { return R(); }
00218     };
00219     
00220     template <class Head, typename R>
00221     class BaseVisitorImpl<Typelist<Head, NullType>, R>
00222         : public Visitor<Head, R>
00223     {
00224     public:
00225         virtual R Visit(Head&)
00226         { return R(); }
00227     };
00228     
00230 // class template BaseVisitable
00232 
00233 template <typename R, typename Visited>
00234 struct DefaultCatchAll
00235 {
00236     static R OnUnknownVisitor(Visited&, BaseVisitor&)
00237     { return R(); }
00238 };
00239 
00241 // class template BaseVisitable
00243 
00244     template 
00245     <
00246         typename R = void, 
00247         template <typename, class> class CatchAll = DefaultCatchAll,
00248         bool ConstVisitable = false
00249     >
00250     class BaseVisitable;
00251 
00252     template<typename R,template <typename, class> class CatchAll>
00253     class BaseVisitable<R, CatchAll, false>
00254     {
00255     public:
00256         typedef R ReturnType;
00257         virtual ~BaseVisitable() {}
00258         virtual ReturnType Accept(BaseVisitor&) = 0;
00259         
00260     protected: // give access only to the hierarchy
00261         template <class T>
00262         static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
00263         {
00264             // Apply the Acyclic Visitor
00265             if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
00266             {
00267                 return p->Visit(visited);
00268             }
00269             return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
00270         }
00271     };
00272 
00273     template<typename R,template <typename, class> class CatchAll>
00274     class BaseVisitable<R, CatchAll, true>
00275     {
00276     public:
00277         typedef R ReturnType;
00278         virtual ~BaseVisitable() {}
00279         virtual ReturnType Accept(BaseVisitor&) const = 0;
00280         
00281     protected: // give access only to the hierarchy
00282         template <class T>
00283         static ReturnType AcceptImpl(const T& visited, BaseVisitor& guest)
00284         {
00285             // Apply the Acyclic Visitor
00286             if (Visitor<T,R,true>* p = dynamic_cast<Visitor<T,R,true>*>(&guest))
00287             {
00288                 return p->Visit(visited);
00289             }
00290             return CatchAll<R, T>::OnUnknownVisitor(const_cast<T&>(visited), guest);
00291         }
00292     };
00293 
00294 
00301 
00302 #define LOKI_DEFINE_VISITABLE() \
00303     virtual ReturnType Accept(::Loki::BaseVisitor& guest) \
00304     { return AcceptImpl(*this, guest); }
00305 
00312 
00313 #define LOKI_DEFINE_CONST_VISITABLE() \
00314     virtual ReturnType Accept(::Loki::BaseVisitor& guest) const \
00315     { return AcceptImpl(*this, guest); }
00316 
00324 
00325     template <typename R, class TList>
00326     class CyclicVisitor : public Visitor<TList, R>
00327     {
00328     public:
00329         typedef R ReturnType;
00330         // using Visitor<TList, R>::Visit;
00331         
00332         template <class Visited>
00333         ReturnType GenericVisit(Visited& host)
00334         {
00335             Visitor<Visited, ReturnType>& subObj = *this;
00336             return subObj.Visit(host);
00337         }
00338     };
00339     
00345 
00346 #define LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
00347     virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
00348     { return guest.GenericVisit(*this); }
00349 
00350 } // namespace Loki
00351 
00352 
00353 
00354 #endif // end file guardian
00355 

Generated on Sun Feb 25 16:52:29 2007 for Loki by  doxygen 1.5.1-p1