From 9a2a524f1e311853d08050be2dcdddc09ac7759a Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:01:29 +0200 Subject: 3.0 --- shared/loki/Visitor.h | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 shared/loki/Visitor.h (limited to 'shared/loki/Visitor.h') 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, +/// public Visitor +/// { +/// 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 +/// { +/// 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::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 +/// { +/// public: +/// LOKI_DEFINE_CONST_VISITABLE() +/// }; +/// \endcode +/// +/// Defining the visitor which only calls const member functions: +/// \code +/// class SomeVisitor : +/// public BaseVisitor // required +/// public Visitor, +/// { +/// public: +/// void Visit(const RasterBitmap&); // visit a RasterBitmap by a const member function +/// }; +/// \endcode +/// +/// \par Example: +/// +/// test/Visitor/main.cpp +//////////////////////////////////////////////////////////////////////////////// + + template + class Visitor; + + template + class Visitor + { + public: + typedef R ReturnType; + typedef T ParamType; + virtual ~Visitor() {} + virtual ReturnType Visit(ParamType&) = 0; + }; + + template + class Visitor + { + 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 +// { +// public: +// void Visit(RasterBitmap&); // visit a RasterBitmap +// void Visit(Paragraph &); // visit a Paragraph +// }; +//////////////////////////////////////////////////////////////////////////////// + + template + class Visitor, R, false> + : public Visitor, public Visitor + { + public: + typedef R ReturnType; + // using Visitor::Visit; + // using Visitor::Visit; + }; + + template + class Visitor, R, false> : public Visitor + { + public: + typedef R ReturnType; + using Visitor::Visit; + }; + + template + class Visitor, R, true> + : public Visitor, public Visitor + { + public: + typedef R ReturnType; + // using Visitor::Visit; + // using Visitor::Visit; + }; + + template + class Visitor, R, true> : 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, + bool ConstVisitable = false + > + class BaseVisitable; + + template class CatchAll> + 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); + } + }; + + template class CatchAll> + class BaseVisitable + { + public: + typedef R ReturnType; + virtual ~BaseVisitable() {} + virtual ReturnType Accept(BaseVisitor&) const = 0; + + protected: // give access only to the hierarchy + template + static ReturnType AcceptImpl(const T& visited, BaseVisitor& guest) + { + // Apply the Acyclic Visitor + if (Visitor* p = dynamic_cast*>(&guest)) + { + return p->Visit(visited); + } + return CatchAll::OnUnknownVisitor(const_cast(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) +//////////////////////////////////////////////////////////////////////////////// + +#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) +//////////////////////////////////////////////////////////////////////////////// + +#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 +//////////////////////////////////////////////////////////////////////////////// + + template + class CyclicVisitor : public Visitor + { + public: + typedef R ReturnType; + // using Visitor::Visit; + + template + ReturnType GenericVisit(Visited& host) + { + Visitor& 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 + -- cgit