summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-07-31 14:39:46 +0000
committerAlan Conway <aconway@apache.org>2007-07-31 14:39:46 +0000
commite316a66b0bfba2ff8b746324544b028cdf9292c0 (patch)
treef807a336102141e65d146ae60a6451e281fbc01c
parent8c69f1fe80520b301a3707b9e7079575f195995e (diff)
downloadqpid-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.h74
-rw-r--r--cpp/src/tests/Visitor.cpp16
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) {