Selaa lähdekoodia

Moved class definitions to own files for intrusive_node, intrusive_iterator.
Fixed bugs that prevented using const_iterator in insert/erase.

Samuel Jaffe 9 vuotta sitten
vanhempi
commit
1c84adca5f
6 muutettua tiedostoa jossa 417 lisäystä ja 284 poistoa
  1. 78 0
      intrusive_iterator.hpp
  2. 5 8
      intrusive_iterator.tpp
  3. 47 276
      intrusive_list.hpp
  4. 244 0
      intrusive_list.tpp
  5. 41 0
      intrusive_node.hpp
  6. 2 0
      intrusive_node.tpp

+ 78 - 0
intrusive_iterator.hpp

@@ -0,0 +1,78 @@
+//
+//  intrusive_iterator.hpp
+//  intrusive_list
+//
+//  Created by Sam Jaffe on 1/7/17.
+//
+
+#pragma once
+
+#include <iterator>
+
+template <typename T> class intrusive_list;
+
+template <typename N>
+class intrusive_iterator : public std::iterator<std::bidirectional_iterator_tag, typename N::value_type> {
+public:
+  typedef std::bidirectional_iterator_tag iterator_category;
+  typedef typename N::value_type value_type;
+  typedef typename N::reference reference;
+  typedef typename N::const_reference const_reference;
+  typedef typename N::pointer pointer;
+  typedef typename N::const_pointer const_pointer;
+public:
+  intrusive_iterator(N* node);
+  
+  reference operator*();
+  const_reference operator*() const;
+  
+  pointer operator->();
+  const_pointer operator->() const;
+  
+  intrusive_iterator operator++(int);
+  intrusive_iterator& operator++();
+  
+  intrusive_iterator operator--(int);
+  intrusive_iterator& operator--();
+  
+  bool operator==(const intrusive_iterator& other) const;
+  bool operator!=(const intrusive_iterator& other) const;
+  
+private:
+  friend intrusive_list<value_type>;
+  
+  N* get() const;
+  N* node_;
+};
+
+template <typename N>
+class const_intrusive_iterator : public std::iterator<std::bidirectional_iterator_tag, typename N::value_type> {
+public:
+  typedef std::bidirectional_iterator_tag iterator_category;
+  typedef typename N::value_type value_type;
+  typedef typename N::reference reference;
+  typedef typename N::const_reference const_reference;
+  typedef typename N::pointer pointer;
+  typedef typename N::const_pointer const_pointer;
+public:
+  const_intrusive_iterator(N* node);
+  
+  const_reference operator*() const;
+  
+  const_pointer operator->() const;
+  
+  const_intrusive_iterator operator++(int);
+  const_intrusive_iterator& operator++();
+  
+  const_intrusive_iterator operator--(int);
+  const_intrusive_iterator& operator--();
+  
+  bool operator==(const const_intrusive_iterator& other) const;
+  bool operator!=(const const_intrusive_iterator& other) const;
+  
+private:
+  friend intrusive_list<value_type>;
+  
+  N* get() const;
+  N* node_;
+};

+ 5 - 8
intrusive_iterator.tpp

@@ -8,6 +8,8 @@
 
 #pragma once
 
+#include "intrusive_iterator.hpp"
+
 template <typename N>
 intrusive_iterator<N>::intrusive_iterator(N* node) :
 node_(node) {
@@ -61,12 +63,7 @@ intrusive_iterator<N>& intrusive_iterator<N>::operator--() {
 }
 
 template <typename N>
-N* intrusive_iterator<N>::get() {
-    return node_;
-}
-
-template <typename N>
-const N* intrusive_iterator<N>::get() const {
+N* intrusive_iterator<N>::get() const {
     return node_;
 }
 
@@ -82,7 +79,7 @@ bool intrusive_iterator<N>::operator!=(const intrusive_iterator<N>& other) const
 
 #pragma mark const_intrusive_iterator
 template <typename N>
-const_intrusive_iterator<N>::const_intrusive_iterator(const N* node) :
+const_intrusive_iterator<N>::const_intrusive_iterator(N* node) :
 node_(node) {
     
 }
@@ -124,7 +121,7 @@ const_intrusive_iterator<N>& const_intrusive_iterator<N>::operator--() {
 }
 
 template <typename N>
-const N* const_intrusive_iterator<N>::get() const {
+N* const_intrusive_iterator<N>::get() const {
     return node_;
 }
 

+ 47 - 276
intrusive_list.hpp

@@ -12,117 +12,10 @@
 #include <limits>
 #include <cstddef>
 
-template <typename T>
-class intrusive_node;
-
-template <typename T>
-class intrusive_list;
-
-template <typename T>
-class intrusive_iterator;
-
-template <typename T>
-class const_intrusive_iterator;
-
-template <typename T>
-class intrusive_node {
-public:
-  typedef T value_type;
-  typedef T& reference;
-  typedef const T& const_reference;
-  typedef T* pointer;
-  typedef const T* const_pointer;
-private:
-  typedef intrusive_node<T>* self;
-public:
-  intrusive_node() = delete;
-  intrusive_node(const intrusive_node&) = delete;
-  intrusive_node(intrusive_node&&) = delete;
-  intrusive_node& operator=(const intrusive_node&) = delete;
-  intrusive_node& operator=(intrusive_node&&) = delete;
-  
-  intrusive_node(pointer ptr);
-  ~intrusive_node();
-  
-private:
-  friend intrusive_list<T>;
-  friend intrusive_iterator<intrusive_node<T> >;
-  friend const_intrusive_iterator<intrusive_node<T> >;
-  
-  pointer ptr_ = nullptr;
-  intrusive_list<T>* list_ = nullptr;
-  self next_ = nullptr;
-  self prev_ = nullptr;
-};
-
-template <typename N>
-class intrusive_iterator : public std::iterator<std::bidirectional_iterator_tag, typename N::value_type> {
-public:
-  typedef std::bidirectional_iterator_tag iterator_category;
-  typedef typename N::value_type value_type;
-  typedef typename N::reference reference;
-  typedef typename N::const_reference const_reference;
-  typedef typename N::pointer pointer;
-  typedef typename N::const_pointer const_pointer;
-public:
-  intrusive_iterator(N* node);
-  
-  reference operator*();
-  const_reference operator*() const;
-  
-  pointer operator->();
-  const_pointer operator->() const;
-  
-  intrusive_iterator operator++(int);
-  intrusive_iterator& operator++();
-  
-  intrusive_iterator operator--(int);
-  intrusive_iterator& operator--();
-  
-  bool operator==(const intrusive_iterator& other) const;
-  bool operator!=(const intrusive_iterator& other) const;
-  
-private:
-  friend intrusive_list<value_type>;
-  
-  N* get();
-  const N* get() const;
-  
-  N* node_;
-};
-
-template <typename N>
-class const_intrusive_iterator : public std::iterator<std::bidirectional_iterator_tag, typename N::value_type> {
-public:
-  typedef std::bidirectional_iterator_tag iterator_category;
-  typedef typename N::value_type value_type;
-  typedef typename N::reference reference;
-  typedef typename N::const_reference const_reference;
-  typedef typename N::pointer pointer;
-  typedef typename N::const_pointer const_pointer;
-public:
-  const_intrusive_iterator(const N* node);
-  
-  const_reference operator*() const;
-  
-  const_pointer operator->() const;
-  
-  const_intrusive_iterator operator++(int);
-  const_intrusive_iterator& operator++();
-  
-  const_intrusive_iterator operator--(int);
-  const_intrusive_iterator& operator--();
-  
-  bool operator==(const const_intrusive_iterator& other) const;
-  bool operator!=(const const_intrusive_iterator& other) const;
-  
-private:
-  friend intrusive_list<value_type>;
-  
-  const N* get() const;
-  
-  const N* node_;
-};
+template <typename T> class intrusive_node;
+template <typename T> class intrusive_list;
+template <typename T> class intrusive_iterator;
+template <typename T> class const_intrusive_iterator;
 
 template <typename T>
 class intrusive_list {
@@ -138,196 +31,74 @@ public:
   typedef typename std::reverse_iterator<iterator> reverse_iterator;
   typedef typename std::reverse_iterator<const_iterator> const_reverse_iterator;
 public:
-  constexpr intrusive_list( node_type T::*node ) :
-  node_(node) {
-    
-  }
+  constexpr intrusive_list( node_type T::*node );
   intrusive_list( const intrusive_list& ) = delete;
   intrusive_list( intrusive_list&& other ) = default;
-  intrusive_list( std::initializer_list<pointer> ilist, node_type T::*node ) :
-  node_(node) {
-    assign(ilist);
-  }
-  ~intrusive_list() {
-    clear();
-  }
+  intrusive_list( std::initializer_list<pointer> ilist, node_type T::*node );
+  ~intrusive_list();
   
   intrusive_list& operator=( const intrusive_list& ) = delete;
-  intrusive_list& operator=( intrusive_list&& other ) {
-    if ( this == & other ) return *this;
-    clear(); // other than this, default
-    node_ = other.node_;
-    size_ = other.size_;
-    head_ = other.head_;
-    other.head_ = &other.end_;
-  }
-  intrusive_list& operator=( std::initializer_list<pointer> ilist ) {
-    assign(ilist);
-  }
+  intrusive_list& operator=( intrusive_list&& other );
+  intrusive_list& operator=( std::initializer_list<pointer> ilist );
   
-  void assign( std::initializer_list<pointer> ilist ) {
-    clear();
-    for (pointer p : ilist) {
-      push_back(p);
-    }
-  }
+  void assign( std::initializer_list<pointer> ilist );
   
-  inline pointer front() {
-    return head_->get();
-  }
-  inline const_pointer front() const {
-    return head_->get();
-  }
+  inline pointer front();
+  inline const_pointer front() const;
   
-  inline pointer back() {
-    return end_.prev_->get();
-  }
-  inline const_pointer back() const {
-    return end_.prev_->get();
-  }
+  inline pointer back();
+  inline const_pointer back() const;
   
-  inline iterator begin() noexcept {
-    return iterator{head_};
-  }
-  inline const_iterator begin() const noexcept {
-    return const_iterator{head_};
-  }
-  inline const_iterator cbegin() const noexcept {
-    return const_iterator{head_};
-  }
+  inline iterator begin() noexcept;
+  inline const_iterator begin() const noexcept;
+  inline const_iterator cbegin() const noexcept;
   
-  inline iterator end() noexcept {
-    return iterator{&end_};
-  }
-  inline const_iterator end() const noexcept {
-    return const_iterator{&end_};
-  }
-  inline const_iterator cend() const noexcept {
-    return const_iterator{&end_};
-  }
+  inline iterator end() noexcept;
+  inline const_iterator end() const noexcept;
+  inline const_iterator cend() const noexcept;
   
-  inline reverse_iterator rbegin() {
-    return reverse_iterator{end()};
-  }
-  inline const_reverse_iterator rbegin() const noexcept {
-    return const_reverse_iterator{end()};
-  }
-  inline const_reverse_iterator crbegin() const noexcept {
-    return const_reverse_iterator{cend()};
-  }
+  inline reverse_iterator rbegin();
+  inline const_reverse_iterator rbegin() const noexcept;
+  inline const_reverse_iterator crbegin() const noexcept;
   
-  inline reverse_iterator rend() noexcept {
-    return reverse_iterator{begin()};
-  }
-  inline const_reverse_iterator rend() const noexcept {
-    return const_reverse_iterator{begin()};
-  }
-  inline const_reverse_iterator crend() const noexcept{
-    return const_reverse_iterator{cbegin()};
-  }
+  inline reverse_iterator rend() noexcept;
+  inline const_reverse_iterator rend() const noexcept;
+  inline const_reverse_iterator crend() const noexcept;
   
-  inline bool empty() const noexcept {
-    return size_ = 0;
-  }
-  inline size_type size() const noexcept {
-    return size_;
-  }
-  inline size_type max_size() const noexcept {
-    return std::numeric_limits<size_type>::max();
-  }
+  inline bool empty() const noexcept;
+  inline size_type size() const noexcept;
+  inline size_type max_size() const noexcept;
   
-  void clear() noexcept {
-    erase(begin(), end());
-  }
+  void clear() noexcept;
   
-  iterator insert(const_iterator pos, pointer value) {
-    node_type* n = &(value->*node_);
-    link(pos.get()->prev_, n);
-    link(n, pos.get());
-    n->list_ = this;
-    ++size_;
-    return iterator{n};
-  }
-  iterator 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;
-    }
-    size_ += ilist.size();
-    return iterator{pos.get()};
-  }
+  iterator insert(const_iterator pos, pointer value);
+  iterator insert(const_iterator pos, std::initializer_list<pointer> ilist);
   
-  iterator erase(iterator pos) {
-    unlink(pos.get());
-    pos.get()->list_ = nullptr;
-    --size_;
-    return iterator{pos.get()->next_};
-  }
-  iterator erase(iterator first, iterator last) {
-    while (first != last) {
-      first = erase(first);
-    }
-    return last;
-  }
+  iterator erase(iterator pos);
+  iterator erase(iterator first, iterator last);
   
-  inline void push_back(pointer value) {
-    link(end_.prev_, &(value->*node_));
-    ++size_;
-  }
+  inline void push_back(pointer value);
   
-  inline void pop_back() {
-    intrusive_node<T> *old = end_.prev_;
-    end_.prev_ = old->prev_;
-    unlink(old);
-    --size_;
-  }
+  inline void pop_back();
   
-  inline void push_front(pointer value) {
-    insert(begin(), value);
-  }
+  inline void push_front(pointer value);
   
-  inline void pop_front() {
-    erase(begin());
-  }
+  inline void pop_front();
   
-  void remove( pointer value ) {
-    node_type* n = &(value->*node_);
-    if (n->list_ == this) {
-      unlink(n);
-      --size_;
-    }
-  }
+  void remove( pointer value );
   template< class UnaryPredicate >
-  void remove_if( UnaryPredicate pred ) {
-    auto it = begin();
-    while (it != end()) {
-      pointer p = it.get()->ptr_;
-      ++it;
-      if (pred(p)) {
-        remove(p);
-      }
-    }
-  }
+  void remove_if( UnaryPredicate pred );
 private:
-  inline void link(node_type* lhs, node_type* rhs) {
-    lhs->next_ = rhs;
-    rhs->prev_ = lhs;
-  }
-  inline void unlink(node_type* node) {
-    if (node->next_) {
-      node->next_->prev_ = node->prev_;
-    }
-    if (node->prev_) {
-      node->prev_->next_ = node->next_;
-    }
-  }
+  inline void link(node_type* lhs, node_type* rhs);
+  inline void unlink(node_type* node);
   
   node_type T::*node_;
-  node_type end_{nullptr}; // secretly const
-  node_type *head_ = &end_;
-  size_type size_;
+  node_type end_{ nullptr }; // secretly const
+  node_type *tail_{ &end_ };
+  node_type *head_{ &end_ };
+  size_type size_{ 0 };
 };
 
 #include "intrusive_iterator.tpp"
 #include "intrusive_node.tpp"
+#include "intrusive_list.tpp"

+ 244 - 0
intrusive_list.tpp

@@ -6,3 +6,247 @@
 //
 
 #pragma once
+
+
+template <typename T>
+constexpr intrusive_list<T>::intrusive_list( node_type T::*node ) :
+node_(node) {
+  
+}
+
+template <typename T>
+intrusive_list<T>::intrusive_list( std::initializer_list<pointer> ilist, node_type T::*node ) :
+node_(node) {
+  assign(ilist);
+}
+
+template <typename T>
+intrusive_list<T>::~intrusive_list() {
+  clear();
+}
+
+template <typename T>
+intrusive_list<T>& intrusive_list<T>::operator=( intrusive_list&& other ) {
+  if ( this == & other ) return *this;
+  clear(); // other than this, default
+  node_ = other.node_;
+  size_ = other.size_;
+  head_ = other.head_;
+  other.head_ = &other.end_;
+}
+
+template <typename T>
+inline intrusive_list<T>& intrusive_list<T>::operator=( std::initializer_list<pointer> ilist ) {
+  assign(ilist);
+}
+
+template <typename T>
+void intrusive_list<T>::assign( std::initializer_list<pointer> ilist ) {
+  clear();
+  for (pointer p : ilist) {
+    push_back(p);
+  }
+}
+
+template <typename T>
+inline typename intrusive_list<T>::pointer intrusive_list<T>::front() {
+  return head_->get();
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_pointer intrusive_list<T>::front() const {
+  return head_->get();
+}
+
+template <typename T>
+inline typename intrusive_list<T>::pointer intrusive_list<T>::back() {
+  return end_.prev_->get();
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_pointer intrusive_list<T>::back() const {
+  return end_.prev_->get();
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::begin() noexcept {
+  return iterator{head_};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::begin() const noexcept {
+  return const_iterator{head_};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::cbegin() const noexcept {
+  return const_iterator{head_};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::end() noexcept {
+  return iterator{tail_};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::end() const noexcept {
+  return const_iterator{tail_};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::cend() const noexcept {
+  return const_iterator{tail_};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::reverse_iterator intrusive_list<T>::rbegin() {
+  return reverse_iterator{end()};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::rbegin() const noexcept {
+  return const_reverse_iterator{end()};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::crbegin() const noexcept {
+  return const_reverse_iterator{cend()};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::reverse_iterator intrusive_list<T>::rend() noexcept {
+  return reverse_iterator{begin()};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::rend() const noexcept {
+  return const_reverse_iterator{begin()};
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator intrusive_list<T>::crend() const noexcept{
+  return const_reverse_iterator{cbegin()};
+}
+
+template <typename T>
+inline bool intrusive_list<T>::empty() const noexcept {
+  return size() == 0;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::size_type intrusive_list<T>::size() const noexcept {
+  return size_;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::size_type intrusive_list<T>::max_size() const noexcept {
+  return std::numeric_limits<size_type>::max();
+}
+
+template <typename T>
+inline void intrusive_list<T>::clear() noexcept {
+  erase(begin(), end());
+}
+
+template <typename T>
+typename intrusive_list<T>::iterator
+  intrusive_list<T>::insert(const_iterator pos, pointer value) {
+  node_type* n = &(value->*node_);
+  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;
+  }
+  size_ += ilist.size();
+  return iterator{pos.get()};
+}
+
+template <typename T>
+typename intrusive_list<T>::iterator intrusive_list<T>::erase(iterator pos) {
+  unlink(pos.get());
+  pos.get()->list_ = nullptr;
+  --size_;
+  return iterator{pos.get()->next_};
+}
+
+template <typename T>
+typename intrusive_list<T>::iterator intrusive_list<T>::erase(iterator first, iterator last) {
+  while (first != last) {
+    first = erase(first);
+  }
+  return last;
+}
+
+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);
+}
+
+template <typename T>
+void intrusive_list<T>::pop_back() {
+  intrusive_node<T> *old = end_.prev_;
+  end_.prev_ = old->prev_;
+  unlink(old);
+  --size_;
+}
+
+template <typename T>
+inline void intrusive_list<T>::push_front(pointer value) {
+  insert(begin(), value);
+}
+
+template <typename T>
+inline void intrusive_list<T>::pop_front() {
+  erase(begin());
+}
+
+template <typename T>
+void intrusive_list<T>::remove( pointer value ) {
+  node_type* n = &(value->*node_);
+  if (n->list_ == this) {
+    unlink(n);
+    --size_;
+  }
+}
+
+template <typename T>
+template< class UnaryPredicate >
+void intrusive_list<T>::remove_if( UnaryPredicate pred ) {
+  auto it = begin();
+  while (it != end()) {
+    pointer p = it.get()->ptr_;
+    ++it;
+    if (pred(p)) {
+      remove(p);
+    }
+  }
+}
+
+template <typename T>
+inline void intrusive_list<T>::link(node_type* lhs, node_type* rhs) {
+  if ( lhs ) { lhs->next_ = rhs; }
+  rhs->prev_ = lhs;
+}
+
+template <typename T>
+inline void intrusive_list<T>::unlink(node_type* node) {
+  if (node->next_) {
+    node->next_->prev_ = node->prev_;
+  }
+  if (node->prev_) {
+    node->prev_->next_ = node->next_;
+  }
+}

+ 41 - 0
intrusive_node.hpp

@@ -0,0 +1,41 @@
+//
+//  intrusive_node.hpp
+//  intrusive_list
+//
+//  Created by Sam Jaffe on 1/7/17.
+//
+
+#pragma once
+
+template <typename T> class intrusive_list;
+
+template <typename T>
+class intrusive_node {
+public:
+  typedef T value_type;
+  typedef T& reference;
+  typedef const T& const_reference;
+  typedef T* pointer;
+  typedef const T* const_pointer;
+private:
+  typedef intrusive_node<T>* self;
+public:
+  intrusive_node() = delete;
+  intrusive_node(const intrusive_node&) = delete;
+  intrusive_node(intrusive_node&&) = delete;
+  intrusive_node& operator=(const intrusive_node&) = delete;
+  intrusive_node& operator=(intrusive_node&&) = delete;
+  
+  intrusive_node(pointer ptr);
+  ~intrusive_node();
+  
+private:
+  friend intrusive_list<T>;
+  friend intrusive_iterator<intrusive_node<T> >;
+  friend const_intrusive_iterator<intrusive_node<T> >;
+  
+  pointer ptr_ = nullptr;
+  intrusive_list<T>* list_ = nullptr;
+  self next_ = nullptr;
+  self prev_ = nullptr;
+};

+ 2 - 0
intrusive_node.tpp

@@ -8,6 +8,8 @@
 
 #pragma once
 
+#include "intrusive_node.hpp"
+
 template <typename T>
 intrusive_node<T>::intrusive_node(pointer ptr) :
 ptr_(ptr) {