//////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2001 by Andrei Alexandrescu // This code accompanies the book: // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // The author or Addison-Wesley Longman make no representations about the // suitability of this software for any purpose. It is provided "as is" // without express or implied warranty. //////////////////////////////////////////////////////////////////////////////// // Last update: June 20, 2001 #ifndef VISITOR_INC_ #define VISITOR_INC_ #include "Typelist.h" #include "HierarchyGenerators.h" namespace Loki { //////////////////////////////////////////////////////////////////////////////// // class template BaseVisitor // The base class of any Acyclic Visitor //////////////////////////////////////////////////////////////////////////////// class BaseVisitor { public: virtual ~BaseVisitor() {} }; //////////////////////////////////////////////////////////////////////////////// // class template Visitor // The building block of Acyclic Visitor //////////////////////////////////////////////////////////////////////////////// template class Visitor { public: typedef R ReturnType; virtual ReturnType Visit(T&) = 0; }; //////////////////////////////////////////////////////////////////////////////// // class template Visitor (specialization) // This specialization is not present in the book. It makes it easier to define // Visitors for multiple types in a shot by using a typelist. Example: // // class SomeVisitor : // public BaseVisitor // required // public Visitor, // public Visitor // { // public: // void Visit(RasterBitmap&); // visit a RasterBitmap // void Visit(Paragraph &); // visit a Paragraph // }; //////////////////////////////////////////////////////////////////////////////// template class Visitor, R> : public Visitor, public Visitor { public: typedef R ReturnType; // using Visitor::Visit; // using Visitor::Visit; }; template class Visitor, R> : public Visitor { public: typedef R ReturnType; using Visitor::Visit; }; //////////////////////////////////////////////////////////////////////////////// // class template BaseVisitorImpl // Implements non-strict visitation (you can implement only part of the Visit // functions) //////////////////////////////////////////////////////////////////////////////// template class BaseVisitorImpl; template class BaseVisitorImpl, R> : public Visitor , public BaseVisitorImpl { public: // using BaseVisitorImpl::Visit; virtual R Visit(Head&) { return R(); } }; template class BaseVisitorImpl, R> : public Visitor { public: virtual R Visit(Head&) { return R(); } }; //////////////////////////////////////////////////////////////////////////////// // class template BaseVisitable //////////////////////////////////////////////////////////////////////////////// template struct DefaultCatchAll { static R OnUnknownVisitor(Visited&, BaseVisitor&) { return R(); } }; //////////////////////////////////////////////////////////////////////////////// // class template BaseVisitable //////////////////////////////////////////////////////////////////////////////// template < typename R = void, template class CatchAll = DefaultCatchAll > class BaseVisitable { public: typedef R ReturnType; virtual ~BaseVisitable() {} virtual ReturnType Accept(BaseVisitor&) = 0; protected: // give access only to the hierarchy template static ReturnType AcceptImpl(T& visited, BaseVisitor& guest) { // Apply the Acyclic Visitor if (Visitor* p = dynamic_cast*>(&guest)) { return p->Visit(visited); } return CatchAll::OnUnknownVisitor(visited, guest); } }; //////////////////////////////////////////////////////////////////////////////// // macro DEFINE_VISITABLE // Put it in every class that you want to make visitable (in addition to // deriving it from BaseVisitable //////////////////////////////////////////////////////////////////////////////// #define DEFINE_VISITABLE() \ virtual ReturnType Accept(Loki::BaseVisitor& guest) \ { return AcceptImpl(*this, guest); } //////////////////////////////////////////////////////////////////////////////// // class template CyclicVisitor // Put it in every class that you want to make visitable (in addition to // deriving it from BaseVisitable //////////////////////////////////////////////////////////////////////////////// template class CyclicVisitor : public Visitor { public: typedef R ReturnType; // using Visitor::Visit; template ReturnType GenericVisit(Visited& host) { Visitor& subObj = *this; return subObj.Visit(host); } }; //////////////////////////////////////////////////////////////////////////////// // macro DEFINE_CYCLIC_VISITABLE // Put it in every class that you want to make visitable by a cyclic visitor //////////////////////////////////////////////////////////////////////////////// #define DEFINE_CYCLIC_VISITABLE(SomeVisitor) \ virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \ { return guest.GenericVisit(*this); } } // namespace Loki //////////////////////////////////////////////////////////////////////////////// // Change log: // March 20: add default argument DefaultCatchAll to BaseVisitable // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! //////////////////////////////////////////////////////////////////////////////// #endif // VISITOR_INC_