浏览代码

Adding new tests

Samuel Jaffe 9 年之前
父节点
当前提交
7806e5d6d8
共有 7 个文件被更改,包括 64 次插入13 次删除
  1. 1 0
      intrusive_iterator.hpp
  2. 5 0
      intrusive_iterator.tpp
  3. 2 3
      intrusive_list.hpp
  4. 27 0
      intrusive_list.t.h
  5. 21 9
      intrusive_list.tpp
  6. 2 0
      intrusive_node.hpp
  7. 6 1
      intrusive_node.tpp

+ 1 - 0
intrusive_iterator.hpp

@@ -22,6 +22,7 @@ public:
   typedef typename N::const_pointer const_pointer;
 public:
   intrusive_iterator(N* node);
+  operator const_intrusive_iterator<N>() const;
   
   reference operator*();
   const_reference operator*() const;

+ 5 - 0
intrusive_iterator.tpp

@@ -16,6 +16,11 @@ node_(node) {
     
 }
 
+template <typename N>
+intrusive_iterator<N>::operator const_intrusive_iterator<N>() const {
+  return node_;
+}
+
 template <typename N>
 auto intrusive_iterator<N>::operator*() -> reference {
     return *(node_->ptr_);

+ 2 - 3
intrusive_list.hpp

@@ -72,23 +72,22 @@ public:
   void clear() noexcept;
   
   iterator insert(const_iterator pos, pointer value);
+  iterator transfer( const_iterator pos, pointer value );
   iterator insert(const_iterator pos, std::initializer_list<pointer> ilist);
   
   iterator erase(iterator pos);
   iterator erase(iterator first, iterator last);
   
   inline void push_back(pointer value);
-  
   inline void pop_back();
-  
   inline void push_front(pointer value);
-  
   inline void pop_front();
   
   void remove( pointer value );
   template< class UnaryPredicate >
   void remove_if( UnaryPredicate pred );
 private:
+  void insert_impl( const_iterator pos, node_type * n );
   inline void link(node_type* lhs, node_type* rhs);
   inline void unlink(node_type* node);
   

+ 27 - 0
intrusive_list.t.h

@@ -27,4 +27,31 @@ public:
     }
     TS_ASSERT( list.empty() );
   }
+  
+  void test_cannot_insert_twice() {
+    intrusive_list<element_stub> list { &element_stub::node1 };
+    element_stub stub;
+    list.push_back( & stub );
+    TS_ASSERT_THROWS( list.push_back( & stub ) , std::logic_error );
+    TS_ASSERT_EQUALS( list.size(), 1 );
+  }
+  
+  void test_insert_cannot_move() {
+    intrusive_list<element_stub> list1 { &element_stub::node1 };
+    intrusive_list<element_stub> list2 { &element_stub::node1 };
+    element_stub stub;
+    list1.push_back( & stub );
+    TS_ASSERT_THROWS( list2.push_back( & stub ) , std::logic_error );
+    TS_ASSERT( list2.empty() );
+  }
+  
+  void test_transfer_relocated_node() {
+    intrusive_list<element_stub> list1 { &element_stub::node1 };
+    intrusive_list<element_stub> list2 { &element_stub::node1 };
+    element_stub stub;
+    list1.push_back( & stub );
+    list2.transfer( list2.end(), & stub );
+    TS_ASSERT( list1.empty() );
+    TS_ASSERT_EQUALS( list2.size(), 1 );
+  }
 };

+ 21 - 9
intrusive_list.tpp

@@ -150,24 +150,39 @@ inline void intrusive_list<T>::clear() noexcept {
 
 template <typename T>
 typename intrusive_list<T>::iterator
-  intrusive_list<T>::insert(const_iterator pos, pointer value) {
+intrusive_list<T>::insert(const_iterator pos, pointer value) {
   node_type* n = &(value->*node_);
+  if ( n->list_ == nullptr ) {
+    insert_impl( pos, n );
+  } else {
+    throw std::logic_error{ "cannot use intrusive_list<T>::insert to perform a splice" };
+  }
+  return iterator{n};
+}
+
+template <typename T>
+typename intrusive_list<T>::iterator
+intrusive_list<T>::transfer(const_iterator pos, pointer value) {
+  node_type* n = &(value->*node_);
+  n->unlink( );
+  insert_impl( pos, n );
+  return iterator{n};
+}
+
+template <typename T>
+void intrusive_list<T>::insert_impl( const_iterator pos, node_type * n ) {
   link(pos.get()->prev_, n);
   link(n, pos.get());
   n->list_ = this;
   ++size_;
-  return iterator{n};
 }
 
 template <typename T>
 typename intrusive_list<T>::iterator
   intrusive_list<T>::insert(const_iterator pos, std::initializer_list<pointer> ilist) {
   for (pointer p : ilist) {
-    link(pos.get()->prev_, p->*node_);
-    link(p->*node_, pos.get());
-    p->*node_->list_ = this;
+    insert( pos, p );
   }
-  size_ += ilist.size();
   return iterator{pos.get()};
 }
 
@@ -189,9 +204,6 @@ typename intrusive_list<T>::iterator intrusive_list<T>::erase(iterator first, it
 
 template <typename T>
 inline void intrusive_list<T>::push_back(pointer value) {
-//  link(end_.prev_, &(value->*node_));
-//  (value->*node_).list_ = this;
-//  ++size_;
   insert(cend(), value);
 }
 

+ 2 - 0
intrusive_node.hpp

@@ -34,6 +34,8 @@ private:
   friend intrusive_iterator<intrusive_node<T> >;
   friend const_intrusive_iterator<intrusive_node<T> >;
   
+  void unlink( );
+  
   pointer ptr_ = nullptr;
   intrusive_list<T>* list_ = nullptr;
   self next_ = nullptr;

+ 6 - 1
intrusive_node.tpp

@@ -18,5 +18,10 @@ ptr_(ptr) {
 
 template <typename T>
 intrusive_node<T>::~intrusive_node() {
-    if (list_) { list_->remove(ptr_); }
+  unlink();
+}
+
+template <typename T>
+void intrusive_node<T>::unlink() {
+  if (list_) { list_->remove(ptr_); }
 }