From e316a66b0bfba2ff8b746324544b028cdf9292c0 Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Tue, 31 Jul 2007 14:39:46 +0000 Subject: src/qpid/framing/Visitor.h: - Removed depdency on Handler, Visitor is a separate pattern. - QPID_VISITOR macro to generate visitor classes replaces use of mpl (Default limits on mpl::vector (20) is too low, concenred about compile time problems if raised to 150. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@561345 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/framing/Visitor.h | 74 +++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 27 deletions(-) (limited to 'cpp/src/qpid') diff --git a/cpp/src/qpid/framing/Visitor.h b/cpp/src/qpid/framing/Visitor.h index fd55c48c60..9753b21954 100644 --- a/cpp/src/qpid/framing/Visitor.h +++ b/cpp/src/qpid/framing/Visitor.h @@ -21,48 +21,68 @@ * */ -#include "Handler.h" - #include -#include -#include -#include +#include +#include namespace qpid { namespace framing { -// FIXME aconway 2007-07-30: Drop linking from handlers, use -// vector > for chains. +/** @file Generic visitor pattern. */ + +/** visit() interface for type T (optional return type R, default void.) + * To create a visitor for a set of types T1, T2 ... do this: + * struct MyVisitor : public Visit, public Visit ... {}; + *@param T Type to visit, must be forward declared, need not be defined. + */ +template struct Visit { + typedef R ReturnType; + typedef T VisitType; + + virtual ~Visit() {} + virtual R visit(T&) = 0; +}; -/** @file Visitor pattern for Handlers. */ -/** - * Interface for a handler visitor, inherits Handler for each T in Types - *@param Types A boost::mpl type sequence, e.g. boost::mpl::vector. +#define QPID_VISITOR_DECL(_1,_2,T) class T; + +#define QPID_VISITOR_BASE(_1,_2,T) , public ::qpid::framing::Visit + +/** Convenience macro to generate a visitor interface. + * QPID_VISITOR(MyVisitor,(A)(B)(C)); is equivalent to: + * @code + * class A; class B; class C; + * class MyVisitor : public Visit , public Visit , public Visit {}; + * @endcode + * @param visitor name of the generated visitor class. + * @param bases a sequence of visitable types in the form (T1)(T2)... + * The odd parenthesized notation is due to quirks of the preprocesser. */ -template -struct HandlerVisitor : public boost::mpl::inherit_linearly< - Types, boost::mpl::inherit > - >::type -{}; +#define QPID_VISITOR(visitor,types) \ + BOOST_PP_SEQ_FOR_EACH(QPID_VISITOR_DECL, _, types) \ + class visitor : public ::qpid::framing::Visit \ + BOOST_PP_SEQ_FOR_EACH(QPID_VISITOR_BASE, _, BOOST_PP_SEQ_TAIL(types)) \ + {} -/** Base class for hierarchy of objects visitable by Visitor */ -template -struct AbstractVisitable { - virtual ~AbstractVisitable() {} - typedef Visitor VisitorType; - virtual void accept(Visitor& v) = 0; +/** Root class for hierarchy of objects visitable by Visitor V. + * Defines virtual accept() + */ +template +struct VisitableRoot { + typedef V VisitorType; + typedef R ReturnType; + virtual ~VisitableRoot() {} + virtual R accept(V& v) = 0; }; -/** Base class for concrete visitable types, implements accept. - * @param T parameter type for appropriate Handler, may be a reference. +/** Base class for concrete visitable classes, implements accept(). + * @param T type of visitable class (CRTP) * @param Base base class to inherit from. */ template -struct ConcreteVisitable : public Base { - typedef typename boost::add_reference::type TRef; +struct Visitable : public Base { void accept(typename Base::VisitorType& v) { - static_cast& >(v).handle(static_cast(*this)); + static_cast& >(v).visit(static_cast(*this)); } }; -- cgit v1.2.1