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 +++++++++++++++++++++++++++--------------- cpp/src/tests/Visitor.cpp | 16 ++++----- 2 files changed, 55 insertions(+), 35 deletions(-) (limited to 'cpp/src') 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)); } }; diff --git a/cpp/src/tests/Visitor.cpp b/cpp/src/tests/Visitor.cpp index f491624cf8..0cb3cf15bb 100644 --- a/cpp/src/tests/Visitor.cpp +++ b/cpp/src/tests/Visitor.cpp @@ -29,19 +29,19 @@ struct DummyA; struct DummyB; struct DummyC; -typedef HandlerVisitor > DummyVisitor; +QPID_VISITOR(DummyVisitor, (DummyA)(DummyB)(DummyC)); -struct DummyFrame : public AbstractVisitable {}; +struct DummyFrame : public VisitableRoot {}; -struct DummyA : public ConcreteVisitable {}; -struct DummyB : public ConcreteVisitable {}; -struct DummyC : public ConcreteVisitable {}; +struct DummyA : public Visitable {}; +struct DummyB : public Visitable {}; +struct DummyC : public Visitable {}; struct TestDummyVisitor : public DummyVisitor { boost::tuple dummies; - void handle(DummyA& a) { dummies.get<0>() = &a; } - void handle(DummyB& b) { dummies.get<1>() = &b; } - void handle(DummyC& c) { dummies.get<2>() = &c; } + void visit(DummyA& a) { dummies.get<0>() = &a; } + void visit(DummyB& b) { dummies.get<1>() = &b; } + void visit(DummyC& c) { dummies.get<2>() = &c; } }; BOOST_AUTO_TEST_CASE(Visitor_accept) { -- cgit v1.2.1