2121#include < cstddef>
2222#include < iterator>
2323
24- namespace intrusive
25- {
26-
2724// Derive your class from this struct to insert to a linked list.
28- template <class Tag = void > struct list_node
25+ template <class Tag = void > struct ilist_node
2926{
30- list_node (list_node *next= NULL , list_node *prev= NULL )
31- : next(next), prev(prev)
27+ ilist_node ()
28+ #ifndef DBUG_OFF
29+ :
30+ next (NULL ), prev(NULL )
31+ #endif
3232 {
3333 }
3434
35- list_node *next;
36- list_node *prev;
35+ ilist_node (ilist_node *next, ilist_node *prev) : next(next), prev(prev) {}
36+
37+ ilist_node *next;
38+ ilist_node *prev;
3739};
3840
3941// Modelled after std::list<T>
40- template <class T , class Tag = void > class list
42+ template <class T , class Tag = void > class ilist
4143{
4244public:
43- typedef list_node <Tag> ListNode;
45+ typedef ilist_node <Tag> ListNode;
4446 class Iterator ;
4547
4648 // All containers in C++ should define these types to implement generic
@@ -103,10 +105,10 @@ template <class T, class Tag= void> class list
103105 private:
104106 ListNode *node_;
105107
106- friend class list ;
108+ friend class ilist ;
107109 };
108110
109- list () : sentinel_(&sentinel_, &sentinel_), size_( 0 ) {}
111+ ilist () : sentinel_(&sentinel_, &sentinel_) {}
110112
111113 reference front () { return *begin (); }
112114 reference back () { return *--end (); }
@@ -129,14 +131,18 @@ template <class T, class Tag= void> class list
129131 reverse_iterator rend () { return reverse_iterator (begin ()); }
130132 const_reverse_iterator rend () const { return reverse_iterator (begin ()); }
131133
132- bool empty () const { return size_ == 0 ; }
133- size_type size () const { return size_; }
134+ bool empty () const { return sentinel_.next == &sentinel_; }
135+
136+ // Not implemented because it's O(N)
137+ // size_type size() const
138+ // {
139+ // return static_cast<size_type>(std::distance(begin(), end()));
140+ // }
134141
135142 void clear ()
136143 {
137144 sentinel_.next = &sentinel_;
138145 sentinel_.prev = &sentinel_;
139- size_= 0 ;
140146 }
141147
142148 iterator insert (iterator pos, reference value)
@@ -150,7 +156,6 @@ template <class T, class Tag= void> class list
150156 static_cast <ListNode &>(value).prev = prev;
151157 static_cast <ListNode &>(value).next = curr;
152158
153- ++size_;
154159 return iterator (&value);
155160 }
156161
@@ -162,13 +167,12 @@ template <class T, class Tag= void> class list
162167 prev->next = next;
163168 next->prev = prev;
164169
165- // This is not required for list functioning. But maybe it'll prevent bugs
166- // and ease debugging.
170+ #ifndef DBUG_OFF
167171 ListNode *curr= pos.node_ ;
168172 curr->prev = NULL ;
169173 curr->next = NULL ;
174+ #endif
170175
171- --size_;
172176 return next;
173177 }
174178
@@ -179,12 +183,63 @@ template <class T, class Tag= void> class list
179183 void pop_front () { erase (begin ()); }
180184
181185 // STL version is O(n) but this is O(1) because an element can't be inserted
182- // several times in the same intrusive list .
186+ // several times in the same ilist .
183187 void remove (reference value) { erase (iterator (&value)); }
184188
185189private:
186190 ListNode sentinel_;
187- size_type size_;
188191};
189192
190- } // namespace intrusive
193+ // Similar to ilist but also has O(1) size() method.
194+ template <class T , class Tag = void > class sized_ilist : public ilist <T, Tag>
195+ {
196+ typedef ilist<T, Tag> BASE;
197+
198+ public:
199+ // All containers in C++ should define these types to implement generic
200+ // container interface.
201+ typedef T value_type;
202+ typedef std::size_t size_type;
203+ typedef std::ptrdiff_t difference_type;
204+ typedef value_type &reference;
205+ typedef const value_type &const_reference;
206+ typedef T *pointer;
207+ typedef const T *const_pointer;
208+ typedef typename BASE::Iterator iterator;
209+ typedef const typename BASE::Iterator const_iterator;
210+ typedef std::reverse_iterator<iterator> reverse_iterator;
211+ typedef std::reverse_iterator<const iterator> const_reverse_iterator;
212+
213+ sized_ilist () : size_(0 ) {}
214+
215+ size_type size () const { return size_; }
216+
217+ void clear ()
218+ {
219+ BASE::clear ();
220+ size_= 0 ;
221+ }
222+
223+ iterator insert (iterator pos, reference value)
224+ {
225+ ++size_;
226+ return BASE::insert (pos, value);
227+ }
228+
229+ iterator erase (iterator pos)
230+ {
231+ --size_;
232+ return BASE::erase (pos);
233+ }
234+
235+ void push_back (reference value) { insert (BASE::end (), value); }
236+ void pop_back () { erase (BASE::end ()); }
237+
238+ void push_front (reference value) { insert (BASE::begin (), value); }
239+ void pop_front () { erase (BASE::begin ()); }
240+
241+ void remove (reference value) { erase (iterator (&value)); }
242+
243+ private:
244+ size_type size_;
245+ };
0 commit comments