Author: aconway
Date: Fri Jan 18 13:44:55 2008
New Revision: 613290

URL: http://svn.apache.org/viewvc?rev=613290&view=rev
Log:

qpid/IList.h: Added public T* getNext(), T* getPrev() to IListNode so node 
subclasses
can follow their own links.

Modified:
    incubator/qpid/trunk/qpid/cpp/src/qpid/IList.h
    incubator/qpid/trunk/qpid/cpp/src/tests/IList.cpp

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/IList.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/IList.h?rev=613290&r1=613289&r2=613290&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/IList.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/IList.h Fri Jan 18 13:44:55 2008
@@ -43,15 +43,25 @@
  * IList<Foo, 0> - uses the 0 links
  * IList<Foo, 1> - uses the 1 links
  [EMAIL PROTECTED]
+ *
+ [EMAIL PROTECTED] T The derived class.
+ [EMAIL PROTECTED] N ID for multiple inheritance.
  */
-template<int N=0> class IListNode  : public virtual RefCounted {
+template<class T, int N=0> class IListNode  : public virtual RefCounted {
     intrusive_ptr<IListNode> prev;
     intrusive_ptr<IListNode> next;
     void insert(IListNode*);    
     void erase();
-  template <class T, int NN> friend class IList;
+    virtual T* self() const {   // Virutal so anchor can hide.
+        return boost::polymorphic_downcast<T*>(const_cast<IListNode*>(this));
+    }
+  friend class IList<T,N>;
   public:
     IListNode(IListNode* p=0) : prev(p), next(p) {}
+    T* getNext() { return next ? next->self() : 0; }
+    T* getPrev() { return prev ? prev->self() : 0; }
+    const T* getNext() const { return next ? next->self() : 0; }
+    const T* getPrev() const { return prev ? prev->self() : 0; }
 };
 
 /**
@@ -62,7 +72,7 @@
  */
 template <class T, int N=0> class IList {
   private:
-    typedef IListNode<N> Node;
+    typedef IListNode<T,N> Node;
 
     template <class R>
     class Iterator :
@@ -109,7 +119,7 @@
     const_iterator last() const { return const_iterator(anchor.prev.get()); }
 
     /// Note: takes a non-const reference, unlike standard containers.
-    void insert(iterator pos, reference x) { x.IListNode<N>::insert(pos.ptr); }
+    void insert(iterator pos, reference x) { x.Node::insert(pos.ptr); }
     void erase(iterator pos) { pos.ptr->erase(); }
     void swap(IList &x) { anchor.swap(x.anchor); }
 
@@ -147,11 +157,13 @@
         Anchor() : Node(this) {}
         // Suppress refcounting for the anchor node.
         void release() const {}
+        // Hide anchor from public get functions.
+        T* self() const { return 0; }
     } anchor;          
 };
 
-template <int N>
-void IListNode<N>::insert(IListNode* node) {
+template <class T, int N>
+void IListNode<T,N>::insert(IListNode* node) {
     assert(!next && !prev);     // Not already in a list.
     assert(node);
     assert(node->next && node->prev);
@@ -161,10 +173,10 @@
     next->prev = this;
 }
 
-template <int N>
-void IListNode<N>::erase() {
+template <class T, int N>
+void IListNode<T,N>::erase() {
     assert(prev && next); 
-    intrusive_ptr<IListNode> self(this); // Protect till exit.
+    intrusive_ptr<IListNode> save(this); // Protect till exit.
     prev->next = next;
     next->prev = prev;
     prev = next = 0;

Modified: incubator/qpid/trunk/qpid/cpp/src/tests/IList.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/IList.cpp?rev=613290&r1=613289&r2=613290&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/IList.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/IList.cpp Fri Jan 18 13:44:55 2008
@@ -49,7 +49,9 @@
 int TestNode::instances = 0;
 ostream& operator<<(ostream& o, const TestNode& n) { return o << n.id; }
 
-struct SingleNode : public TestNode, public IListNode<> { SingleNode(char i) : 
TestNode(i) {} };
+struct SingleNode : public TestNode, public IListNode<SingleNode> {
+    SingleNode(char i) : TestNode(i) {}
+};
 typedef IList<SingleNode> TestList;
 
 struct Fixture {
@@ -119,8 +121,16 @@
     {
         TestList l;
         l.push_back(*a);
+        BOOST_CHECK(a->getNext() == 0);
+        BOOST_CHECK(a->getPrev() == 0);
         l.push_back(*b);
+        BOOST_CHECK(a->getNext() == b.get());
+        BOOST_CHECK(a->getPrev() == 0);
+        BOOST_CHECK(b->getNext() == 0);
+        BOOST_CHECK(b->getPrev() == a.get());
         l.push_back(*c);
+        BOOST_CHECK(b->getNext() == c.get());
+        BOOST_CHECK(c->getPrev() == b.get());
     
         TestList::iterator i = l.begin();
         BOOST_CHECK_EQUAL(*i, *a);
@@ -155,7 +165,11 @@
     BOOST_CHECK_EQUAL(0, SingleNode::instances);
 }
 
-struct MultiNode : public TestNode, public IListNode<0>, public IListNode<1>, 
public IListNode<2> {
+struct MultiNode : public TestNode,
+                   public IListNode<MultiNode, 0>,
+                   public IListNode<MultiNode, 1>,
+                   public IListNode<MultiNode, 2>
+{
     MultiNode(char c) : TestNode(c) {}
 };
 


Reply via email to