summaryrefslogtreecommitdiff
path: root/shared/loki/Visitor.h
diff options
context:
space:
mode:
Diffstat (limited to 'shared/loki/Visitor.h')
-rw-r--r--shared/loki/Visitor.h355
1 files changed, 355 insertions, 0 deletions
diff --git a/shared/loki/Visitor.h b/shared/loki/Visitor.h
new file mode 100644
index 00000000..4425a9fa
--- /dev/null
+++ b/shared/loki/Visitor.h
@@ -0,0 +1,355 @@
+////////////////////////////////////////////////////////////////////////////////
+// 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.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_VISITOR_INC_
+#define LOKI_VISITOR_INC_
+
+// $Id: Visitor.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+/// \defgroup VisitorGroup Visitor
+
+#include "Typelist.h"
+#include "HierarchyGenerators.h"
+
+namespace Loki
+{
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class BaseVisitor
+///
+/// \ingroup VisitorGroup
+/// The base class of any Acyclic Visitor
+////////////////////////////////////////////////////////////////////////////////
+
+ class BaseVisitor
+ {
+ public:
+ virtual ~BaseVisitor() {}
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class Visitor
+///
+/// \ingroup VisitorGroup
+/// The building block of Acyclic Visitor
+///
+/// \par Usage
+///
+/// Defining the visitable class:
+///
+/// \code
+/// class RasterBitmap : public BaseVisitable<>
+/// {
+/// public:
+/// LOKI_DEFINE_VISITABLE()
+/// };
+/// \endcode
+///
+/// Way 1 to define a visitor:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<RasterBitmap>,
+/// public Visitor<Paragraph>
+/// {
+/// public:
+/// void Visit(RasterBitmap&); // visit a RasterBitmap
+/// void Visit(Paragraph &); // visit a Paragraph
+/// };
+/// \endcode
+///
+/// Way 2 to define the visitor:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
+/// {
+/// public:
+/// void Visit(RasterBitmap&); // visit a RasterBitmap
+/// void Visit(Paragraph &); // visit a Paragraph
+/// };
+/// \endcode
+///
+/// Way 3 to define the visitor:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<Seq<RasterBitmap, Paragraph>::Type>
+/// {
+/// public:
+/// void Visit(RasterBitmap&); // visit a RasterBitmap
+/// void Visit(Paragraph &); // visit a Paragraph
+/// };
+/// \endcode
+///
+/// \par Using const visit functions:
+///
+/// Defining the visitable class (true for const):
+///
+/// \code
+/// class RasterBitmap : public BaseVisitable<void, DefaultCatchAll, true>
+/// {
+/// public:
+/// LOKI_DEFINE_CONST_VISITABLE()
+/// };
+/// \endcode
+///
+/// Defining the visitor which only calls const member functions:
+/// \code
+/// class SomeVisitor :
+/// public BaseVisitor // required
+/// public Visitor<RasterBitmap, void, true>,
+/// {
+/// public:
+/// void Visit(const RasterBitmap&); // visit a RasterBitmap by a const member function
+/// };
+/// \endcode
+///
+/// \par Example:
+///
+/// test/Visitor/main.cpp
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class T, typename R = void, bool ConstVisit = false>
+ class Visitor;
+
+ template <class T, typename R>
+ class Visitor<T, R, false>
+ {
+ public:
+ typedef R ReturnType;
+ typedef T ParamType;
+ virtual ~Visitor() {}
+ virtual ReturnType Visit(ParamType&) = 0;
+ };
+
+ template <class T, typename R>
+ class Visitor<T, R, true>
+ {
+ public:
+ typedef R ReturnType;
+ typedef const T ParamType;
+ virtual ~Visitor() {}
+ virtual ReturnType Visit(ParamType&) = 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<LOKI_TYPELIST_2(RasterBitmap, Paragraph)>
+// {
+// public:
+// void Visit(RasterBitmap&); // visit a RasterBitmap
+// void Visit(Paragraph &); // visit a Paragraph
+// };
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class Head, class Tail, typename R>
+ class Visitor<Typelist<Head, Tail>, R, false>
+ : public Visitor<Head, R, false>, public Visitor<Tail, R, false>
+ {
+ public:
+ typedef R ReturnType;
+ // using Visitor<Head, R>::Visit;
+ // using Visitor<Tail, R>::Visit;
+ };
+
+ template <class Head, typename R>
+ class Visitor<Typelist<Head, NullType>, R, false> : public Visitor<Head, R, false>
+ {
+ public:
+ typedef R ReturnType;
+ using Visitor<Head, R, false>::Visit;
+ };
+
+ template <class Head, class Tail, typename R>
+ class Visitor<Typelist<Head, Tail>, R, true>
+ : public Visitor<Head, R, true>, public Visitor<Tail, R, true>
+ {
+ public:
+ typedef R ReturnType;
+ // using Visitor<Head, R>::Visit;
+ // using Visitor<Tail, R>::Visit;
+ };
+
+ template <class Head, typename R>
+ class Visitor<Typelist<Head, NullType>, R, true> : public Visitor<Head, R, true>
+ {
+ public:
+ typedef R ReturnType;
+ using Visitor<Head, R, true>::Visit;
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BaseVisitorImpl
+// Implements non-strict visitation (you can implement only part of the Visit
+// functions)
+////////////////////////////////////////////////////////////////////////////////
+
+ template <class TList, typename R = void> class BaseVisitorImpl;
+
+ template <class Head, class Tail, typename R>
+ class BaseVisitorImpl<Typelist<Head, Tail>, R>
+ : public Visitor<Head, R>
+ , public BaseVisitorImpl<Tail, R>
+ {
+ public:
+ // using BaseVisitorImpl<Tail, R>::Visit;
+
+ virtual R Visit(Head&)
+ { return R(); }
+ };
+
+ template <class Head, typename R>
+ class BaseVisitorImpl<Typelist<Head, NullType>, R>
+ : public Visitor<Head, R>
+ {
+ public:
+ virtual R Visit(Head&)
+ { return R(); }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BaseVisitable
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename R, typename Visited>
+struct DefaultCatchAll
+{
+ static R OnUnknownVisitor(Visited&, BaseVisitor&)
+ { return R(); }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// class template BaseVisitable
+////////////////////////////////////////////////////////////////////////////////
+
+ template
+ <
+ typename R = void,
+ template <typename, class> class CatchAll = DefaultCatchAll,
+ bool ConstVisitable = false
+ >
+ class BaseVisitable;
+
+ template<typename R,template <typename, class> class CatchAll>
+ class BaseVisitable<R, CatchAll, false>
+ {
+ public:
+ typedef R ReturnType;
+ virtual ~BaseVisitable() {}
+ virtual ReturnType Accept(BaseVisitor&) = 0;
+
+ protected: // give access only to the hierarchy
+ template <class T>
+ static ReturnType AcceptImpl(T& visited, BaseVisitor& guest)
+ {
+ // Apply the Acyclic Visitor
+ if (Visitor<T,R>* p = dynamic_cast<Visitor<T,R>*>(&guest))
+ {
+ return p->Visit(visited);
+ }
+ return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
+ }
+ };
+
+ template<typename R,template <typename, class> class CatchAll>
+ class BaseVisitable<R, CatchAll, true>
+ {
+ public:
+ typedef R ReturnType;
+ virtual ~BaseVisitable() {}
+ virtual ReturnType Accept(BaseVisitor&) const = 0;
+
+ protected: // give access only to the hierarchy
+ template <class T>
+ static ReturnType AcceptImpl(const T& visited, BaseVisitor& guest)
+ {
+ // Apply the Acyclic Visitor
+ if (Visitor<T,R,true>* p = dynamic_cast<Visitor<T,R,true>*>(&guest))
+ {
+ return p->Visit(visited);
+ }
+ return CatchAll<R, T>::OnUnknownVisitor(const_cast<T&>(visited), guest);
+ }
+ };
+
+
+////////////////////////////////////////////////////////////////////////////////
+/// \def LOKI_DEFINE_VISITABLE()
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable
+/// (in addition to deriving it from BaseVisitable<R>)
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_VISITABLE() \
+ virtual ReturnType Accept(::Loki::BaseVisitor& guest) \
+ { return AcceptImpl(*this, guest); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// \def LOKI_DEFINE_CONST_VISITABLE()
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable by const member
+/// functions (in addition to deriving it from BaseVisitable<R>)
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_CONST_VISITABLE() \
+ virtual ReturnType Accept(::Loki::BaseVisitor& guest) const \
+ { return AcceptImpl(*this, guest); }
+
+////////////////////////////////////////////////////////////////////////////////
+/// \class CyclicVisitor
+///
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable (in addition to
+/// deriving it from BaseVisitable<R>
+////////////////////////////////////////////////////////////////////////////////
+
+ template <typename R, class TList>
+ class CyclicVisitor : public Visitor<TList, R>
+ {
+ public:
+ typedef R ReturnType;
+ // using Visitor<TList, R>::Visit;
+
+ template <class Visited>
+ ReturnType GenericVisit(Visited& host)
+ {
+ Visitor<Visited, ReturnType>& subObj = *this;
+ return subObj.Visit(host);
+ }
+ };
+
+////////////////////////////////////////////////////////////////////////////////
+/// \def LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor)
+/// \ingroup VisitorGroup
+/// Put it in every class that you want to make visitable by a cyclic visitor
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_DEFINE_CYCLIC_VISITABLE(SomeVisitor) \
+ virtual SomeVisitor::ReturnType Accept(SomeVisitor& guest) \
+ { return guest.GenericVisit(*this); }
+
+} // namespace Loki
+
+
+
+#endif // end file guardian
+
bgstack15