diff options
author | Alan Conway <aconway@apache.org> | 2007-07-31 14:39:46 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2007-07-31 14:39:46 +0000 |
commit | e316a66b0bfba2ff8b746324544b028cdf9292c0 (patch) | |
tree | f807a336102141e65d146ae60a6451e281fbc01c | |
parent | 8c69f1fe80520b301a3707b9e7079575f195995e (diff) | |
download | qpid-python-e316a66b0bfba2ff8b746324544b028cdf9292c0.tar.gz |
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
-rw-r--r-- | cpp/src/qpid/framing/Visitor.h | 74 | ||||
-rw-r--r-- | cpp/src/tests/Visitor.cpp | 16 |
2 files changed, 55 insertions, 35 deletions
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 <boost/mpl/vector.hpp> -#include <boost/mpl/inherit.hpp> -#include <boost/mpl/inherit_linearly.hpp> -#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/preprocessor/seq/for_each.hpp> namespace qpid { namespace framing { -// FIXME aconway 2007-07-30: Drop linking from handlers, use -// vector<shared_ptr<Handler<T> > 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<T1>, public Visit<T2> ... {}; + *@param T Type to visit, must be forward declared, need not be defined. + */ +template <class T, class R=void> 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<T> 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<T> + +/** 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<A> , public Visit<B> , public Visit<C> {}; + * @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 <class Types> -struct HandlerVisitor : public boost::mpl::inherit_linearly< - Types, boost::mpl::inherit<boost::mpl::_1, Handler<boost::mpl::_2> > - >::type -{}; +#define QPID_VISITOR(visitor,types) \ + BOOST_PP_SEQ_FOR_EACH(QPID_VISITOR_DECL, _, types) \ + class visitor : public ::qpid::framing::Visit<BOOST_PP_SEQ_HEAD(types)> \ + BOOST_PP_SEQ_FOR_EACH(QPID_VISITOR_BASE, _, BOOST_PP_SEQ_TAIL(types)) \ + {} -/** Base class for hierarchy of objects visitable by Visitor */ -template <class Visitor> -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 <class V, class R=void> +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 <class T, class Base> -struct ConcreteVisitable : public Base { - typedef typename boost::add_reference<T>::type TRef; +struct Visitable : public Base { void accept(typename Base::VisitorType& v) { - static_cast<Handler<T>& >(v).handle(static_cast<TRef>(*this)); + static_cast<Visit<T>& >(v).visit(static_cast<T&>(*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<boost::mpl::vector<DummyA&, DummyB&, DummyC&> > DummyVisitor; +QPID_VISITOR(DummyVisitor, (DummyA)(DummyB)(DummyC)); -struct DummyFrame : public AbstractVisitable<DummyVisitor> {}; +struct DummyFrame : public VisitableRoot<DummyVisitor> {}; -struct DummyA : public ConcreteVisitable<DummyA&, DummyFrame> {}; -struct DummyB : public ConcreteVisitable<DummyB&, DummyFrame> {}; -struct DummyC : public ConcreteVisitable<DummyC&, DummyFrame> {}; +struct DummyA : public Visitable<DummyA, DummyFrame> {}; +struct DummyB : public Visitable<DummyB, DummyFrame> {}; +struct DummyC : public Visitable<DummyC, DummyFrame> {}; struct TestDummyVisitor : public DummyVisitor { boost::tuple<DummyA*, DummyB*, DummyC*> 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) { |