Author: aconway
Date: Tue Jul 31 07:39:46 2007
New Revision: 561345
URL: http://svn.apache.org/viewvc?view=rev&rev=561345
Log:
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.
Modified:
incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Visitor.h
incubator/qpid/trunk/qpid/cpp/src/tests/Visitor.cpp
Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Visitor.h
URL:
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Visitor.h?view=diff&rev=561345&r1=561344&r2=561345
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Visitor.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/framing/Visitor.h Tue Jul 31
07:39:46 2007
@@ -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> ... {};
+ [EMAIL PROTECTED] 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;
+};
+
+
+#define QPID_VISITOR_DECL(_1,_2,T) class T;
-/** @file Visitor pattern for Handlers. */
+#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.
+ */
+#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)) \
+ {}
-/**
- * Interface for a handler visitor, inherits Handler<T> for each T in Types
- [EMAIL PROTECTED] Types A boost::mpl type sequence, e.g. boost::mpl::vector.
+/** Root class for hierarchy of objects visitable by Visitor V.
+ * Defines virtual accept()
*/
-template <class Types>
-struct HandlerVisitor : public boost::mpl::inherit_linearly<
- Types, boost::mpl::inherit<boost::mpl::_1, Handler<boost::mpl::_2> >
- >::type
-{};
-
-/** 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;
+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));
}
};
Modified: incubator/qpid/trunk/qpid/cpp/src/tests/Visitor.cpp
URL:
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/Visitor.cpp?view=diff&rev=561345&r1=561344&r2=561345
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/Visitor.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/Visitor.cpp Tue Jul 31 07:39:46 2007
@@ -29,19 +29,19 @@
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) {