source: soft/giet_vm/mover/include/libelfpp/dpp/linked_list @ 160

Last change on this file since 160 was 160, checked in by karaoui, 12 years ago

giet-vm new version

File size: 23.3 KB
Line 
1/* -*- c++ -*-
2
3   C++ Internal storage linked list container.
4
5   This file is part of the dpp library of C++ template classes
6
7   doc: http://diaxen.ssji.net/dpp/index.html
8   repo: https://www.ssji.net/svn/projets/trunk/libdpp
9
10   This program is free software: you can redistribute it and/or
11   modify it under the terms of the GNU Lesser General Public License
12   as published by the Free Software Foundation, either version 3 of
13   the License, or (at your option) any later version.
14
15   This program is distributed in the hope that it will be useful, but
16   WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18   Lesser General Public License for more details.
19
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program.  If not, see
22   <http://www.gnu.org/licenses/>.
23
24   (c) 2008-2011 Alexandre Becoulet <alexandre.becoulet@free.fr>
25
26*/
27
28#ifndef DPP_LINKED_LIST_HH_
29#define DPP_LINKED_LIST_HH_
30
31#include <iterator>
32#include <cassert>
33
34/** @file @module{Linked list container} */
35
36namespace dpp {
37
38class linked_list_node;
39
40template <class X, int id = -1, bool smart = false>
41class linked_list_item;
42
43template <class X, int id = -1, bool smart = false, class ItemBase = X>
44class linked_list;
45
46template <class X, int id, class Xnode, bool forward, bool smart>
47class linked_list_iterator;
48
49//////////////////////////////////////////////////////////////////////
50//      linked_list node class
51//////////////////////////////////////////////////////////////////////
52
53/** @short Linked list internal node class
54    @module{Linked list container}
55    @header dpp/linked_list
56    @internal
57 */
58
59class linked_list_node
60{
61  template <class, int, bool, class> friend class linked_list;
62  template <class, int, bool> friend class linked_list_item;
63  template <class, int, class, bool, bool> friend class linked_list_iterator;
64
65  linked_list_node *m_next;
66  linked_list_node *m_prev;
67
68  linked_list_node(linked_list_node *next, linked_list_node *prev)
69    : m_next(next),
70      m_prev(prev)
71  {
72  }
73
74  linked_list_node()
75  {
76  }
77
78  linked_list_node(linked_list_node &l)
79    : m_next(l.m_next),
80      m_prev(l.m_prev)
81  {
82  }
83
84};
85
86//////////////////////////////////////////////////////////////////////
87//      linked_list iterator class
88//////////////////////////////////////////////////////////////////////
89
90/** @short Linked list iterator class
91    @module{Linked list container}
92    @header dpp/linked_list
93    @internal
94 */
95
96template <class X, int id, class Xnode, bool forward, bool smart>
97class linked_list_iterator
98{
99  template <class, int, bool, class> friend class linked_list;
100  template <class, int, bool> friend class linked_list_item;
101  template <class, int, class, bool, bool> friend class linked_list_iterator;
102
103  linked_list_iterator(Xnode *i)
104    : m_item(i)
105  {
106  }
107
108  Xnode *m_item;
109
110public:
111
112  /** @multiple Standard STL container typedef. */
113  typedef linked_list_item<X, id, smart> item_type;
114  typedef X value_type;
115  typedef X & reference;
116  typedef X * pointer;
117  typedef ssize_t difference_type;
118  typedef std::bidirectional_iterator_tag iterator_category;
119  /** */
120
121  linked_list_iterator(const linked_list_iterator &i)
122    : m_item(i.m_item)
123  {
124  }
125
126  template <class T, class N>
127  linked_list_iterator(const linked_list_iterator<T, id, N, forward, smart> &i)
128    : m_item(i.m_item)
129  {
130    // raise error on invalid iterator convertion
131    static_cast<X*>((T*)0);
132  }
133
134  linked_list_iterator()
135  {
136  }
137
138  linked_list_iterator & operator++()
139  {
140    assert(m_item->m_next || !"iterator points to orphan item");
141    m_item = forward ? m_item->m_next : m_item->m_prev;
142    return *this;
143  }
144
145  linked_list_iterator operator++(int)
146  {
147    assert(m_item->m_next || !"iterator points to orphan item");
148    linked_list_iterator tmp(*this);
149    m_item = forward ? m_item->m_next : m_item->m_prev;
150    return tmp;
151  }
152
153  linked_list_iterator & operator--()
154  {
155    assert(m_item->m_next || !"iterator points to orphan item");
156    m_item = forward ? m_item->m_prev : m_item->m_next;
157    return *this;
158  }
159
160  linked_list_iterator operator--(int)
161  {
162    assert(m_item->m_next || !"iterator points to orphan item");
163    linked_list_iterator tmp(*this);
164    m_item = forward ? m_item->m_prev : m_item->m_next;
165    return tmp;
166  }
167
168  X & operator*() const
169  {
170    return const_cast<X &>(
171             static_cast<const X &>(
172               static_cast<const item_type &>(*m_item)));
173  }
174
175  X * operator->() const
176  {
177    return const_cast<X *>(
178             static_cast<const X *>(
179               static_cast<const item_type *>(m_item)));
180  }
181
182  bool operator==(const linked_list_iterator &i) const
183  {
184    return m_item == i.m_item;
185  }
186
187  bool operator!=(const linked_list_iterator &i) const
188  {
189    return m_item != i.m_item;
190  }
191
192};
193
194//////////////////////////////////////////////////////////////////////
195//      linked_list container class
196//////////////////////////////////////////////////////////////////////
197
198/** @short Linked list container class
199    @module{Linked list container}
200    @header dpp/linked_list
201    @main
202    @showvalue
203
204    @This implements the internal storage linked list container.
205
206    Item class must inherit from the @ref linked_list_item class
207    in order to be a valid @ref linked_list container item.
208
209    The @tt id template parameter may be used to define several
210    distinct list containers so that items can be part of more than
211    one list.
212
213    Linked list can be used in @tt smart mode. Smart lists will automatically
214    remove items from current list when inserting in an other list. Non-smart
215    list will raise false assertion if non-orphan items are used the
216    wrong way.
217
218    When the linked list contained class doesn't directly inherit from
219    @ref linked_list_item, the base class which inherits from @ref
220    linked_list_item must be passed as @tt ItemBase template parameter.
221*/
222
223template <class X, int id, bool smart, class ItemBase>
224class linked_list
225{
226  template <class, int, bool> friend class linked_list_item;
227
228  typedef bool _predicate(const X &a, const X &b);
229
230public:
231  /** @multiple Standard STL container typedef. */
232
233  typedef linked_list_item<ItemBase, id, smart> item_type;
234
235  typedef linked_list_iterator<X, id, linked_list_node, true, smart> iterator;
236  typedef linked_list_iterator<X, id, const linked_list_node, true, smart> const_iterator;
237  typedef linked_list_iterator<X, id, linked_list_node, false, smart> reverse_iterator;
238  typedef linked_list_iterator<X, id, const linked_list_node, false, smart> const_reverse_iterator;
239
240  typedef X value_type;
241  typedef X & reference;
242  typedef const X & const_reference;
243  typedef X * pointer;
244  typedef const X * const_pointer;
245  typedef size_t size_type;
246  typedef ssize_t difference_type;
247  /** */
248
249private:
250
251  void _empty()
252  {
253    m_root.m_next = m_root.m_prev = &m_root;
254  }
255
256  static void _insert_post(linked_list_node *a, item_type *b)
257  {
258    static_cast<X*>(b)->linked_list_pre_insert();
259    b->_check_orphan();
260    b->m_prev = a;
261    a->m_next->m_prev = b;
262    b->m_next = a->m_next;
263    a->m_next = b;
264  }
265
266  static void _insert_pre(linked_list_node *a, item_type *b)
267  {
268    static_cast<X*>(b)->linked_list_pre_insert();
269    b->_check_orphan();
270    b->m_next = a;
271    a->m_prev->m_next = b;
272    b->m_prev = a->m_prev;
273    a->m_prev = b;
274  }
275
276  static void _remove(item_type *pos)
277  {
278    pos->_check_not_orphan();
279    pos->m_prev->m_next = pos->m_next;
280    pos->m_next->m_prev = pos->m_prev;
281    pos->_set_orphan();
282    static_cast<X*>(pos)->linked_list_post_remove();
283  }
284
285  static void _swap(item_type *a, item_type *b)
286  {
287    a->m_next->m_prev = a->m_prev->m_next = b;
288    b->m_next->m_prev = b->m_prev->m_next = a;
289    std::swap(a->m_prev, b->m_prev);
290    std::swap(a->m_next, b->m_next);
291  }
292
293  static void _replace(item_type *out, item_type *in)
294  {
295    if (out == in)
296      return;
297    out->_check_not_orphan();
298    static_cast<X*>(in)->linked_list_pre_insert();
299    in->_check_orphan();
300    out->m_prev->m_next = out->m_next->m_prev = in;
301    in->m_prev = out->m_prev;
302    in->m_next = out->m_next;
303    out->_set_orphan();
304    static_cast<X*>(out)->linked_list_post_remove();
305  }
306
307  // rebuild from a null terminated singly list
308  void _rebuild(linked_list_node *list)
309  {
310    linked_list_node *prev;
311    m_root.m_next = list;
312
313    for (prev = &m_root; list; list = list->m_next)
314      {
315        list->m_prev = prev;
316        prev = list;
317      }
318
319    prev->m_next = &m_root;
320    m_root.m_prev = prev;
321  }
322
323  // default sort predicate
324  static bool _default_predicate(const X &a, const X &b)
325  {
326    return a < b;
327  }
328
329  // sublist merging function
330  static linked_list_node * _merge(linked_list_node *a, linked_list_node *b, _predicate *func)
331  {
332    linked_list_node *first, *last;
333
334    /* choose list head */
335    if (func(static_cast<X&>(static_cast<item_type &>(*a)),
336             static_cast<X&>(static_cast<item_type &>(*b))))
337      a = (last = first = a)->m_next;
338    else
339      b = (last = first = b)->m_next;
340
341    /* merge lists */
342    while (a && b)
343      if (func(static_cast<X&>(static_cast<item_type &>(*a)),
344               static_cast<X&>(static_cast<item_type &>(*b))))
345        a = (last = last->m_next = a)->m_next;
346      else
347        b = (last = last->m_next = b)->m_next;
348
349    last->m_next = a ? a : b;
350
351    return first;
352  }
353
354  linked_list(const linked_list &l);
355  linked_list & operator=(const linked_list &);
356
357  linked_list_node m_root;
358
359public:
360
361  /** @This creates an empty list. */
362  linked_list()
363    : m_root(&m_root, &m_root)
364  {
365  }
366
367  /** @This set all contained items as orphan. */
368  ~linked_list()
369  {
370    for (linked_list_node *i = m_root.m_prev; i != &m_root; i = i->m_prev)
371      {
372        item_type *t = static_cast<item_type*>(i);
373        t->_set_orphan();
374        static_cast<X*>(t)->linked_list_post_remove();
375      }
376  }
377
378  /** @This creates a list from item iterators. */
379  template <class input_iterator>
380  linked_list(input_iterator first, input_iterator last)
381    : m_root(&m_root, &m_root)
382  {
383    for (input_iterator i = first; i != last; i++)
384      _insert_pre(&m_root, &*i);
385  }
386
387  /** @This push an item in front of this list. */
388  void push_front(X &i)
389  {
390    _insert_post(&m_root, static_cast<item_type*>(&i));
391  }
392
393  /** @This push an item at the end of this list.
394      @csee linked_list_item::push_back
395   */
396  void push_back(X &i)
397  {
398    _insert_pre(&m_root, static_cast<item_type*>(&i));
399  }
400
401  /** @This removes first item from this list.
402      @csee linked_list_item::push_back
403   */
404  void pop_front()
405  {
406    _remove(static_cast<item_type*>(m_root.m_next));
407  }
408
409  /** @This removes last item from this list. */
410  void pop_back()
411  {
412    _remove(static_cast<item_type*>(m_root.m_prev));
413  }
414
415  /** @This inserts an item at specified location in this list.
416      @return an iterator to inserted item */
417  iterator insert(const iterator &pos, X &i)
418  {
419    item_type *li = static_cast<item_type*>(&i);
420    _insert_pre(pos.m_item, li);
421    return iterator(li);
422  }
423
424  /** @This inserts multiple items at specified position in this list.
425      @return an iterator to first inserted item */
426  template <class input_iterator>
427  iterator insert(const iterator &pos, input_iterator first, input_iterator last)
428  {
429    for (input_iterator i = first; i != last; i++)
430      _insert_pre(pos.m_item, &*i);
431    return iterator(static_cast<item_type*>(&*first));
432  }
433
434  /** @This removes the item at specified position in this list.
435      @return an iterator to next item */
436  iterator erase(iterator pos)
437  {
438    linked_list_node *next = pos.m_item->m_next;
439    _remove(static_cast<item_type*>(pos.m_item));
440    return iterator(static_cast<item_type*>(next));
441  }
442
443  /** @This removes all items in specified [range) in this list.
444      @return an iterator to the next item */
445  iterator erase(iterator first, iterator last)
446  {
447    item_type *f = static_cast<item_type*>(&*first);
448    item_type *l = static_cast<item_type*>(&*last);
449
450    f->m_prev->m_next = l;
451
452    for (linked_list_node *i = l->m_prev; i != f->m_prev; i = i->m_prev)
453      {
454        item_type *t = static_cast<item_type*>(i);
455        t->_set_orphan();
456        static_cast<X*>(t)->linked_list_post_remove();
457      }
458
459    l->m_prev = f->m_prev;
460
461    return iterator(l);
462  }
463
464  /** @This swaps lists contents. */
465  void swap(linked_list &x)
466  {
467    _swap(static_cast<item_type*>(&m_root),
468          static_cast<item_type*>(&x.m_root));
469  }
470
471  /** @This removes all items from this list. */
472  void clear()
473  {
474    for (linked_list_node *i = m_root.m_prev; i != &m_root; i = i->m_prev)
475      {
476        item_type *t = static_cast<item_type*>(i);
477        t->_set_orphan();
478        static_cast<X*>(t)->linked_list_post_remove();
479      }
480
481    m_root.m_next = m_root.m_prev = &m_root;
482  }
483
484  /** @This removes all items matching specified value from this list
485      @csee linked_list_item::remove
486  */
487  void remove(const X &v)
488  {
489    for (iterator i = begin(); i != end();)
490      {
491        if (*i == v)
492          i = erase(i);
493        else
494          ++i;
495      }
496  }
497
498  /** @This replaces an item by an other item in this list.
499      @return an iterator to replacement item
500      @csee linked_list_item::replace */
501  static iterator replace(X &out, X &in)
502  {
503    item_type *i = static_cast<item_type*>(&in);
504    _replace(i, static_cast<item_type*>(&out));
505    return iterator(i);
506  }
507
508  /** @This tests if this list is empty */
509  bool empty() const
510  {
511    return m_root.m_next == &m_root;
512  }
513
514  /** @This returns list item count, takes O(n). */
515  size_type size() const
516  {
517    size_t s = 0;
518
519    for (const_iterator i = begin(); i != end(); ++i)
520      s++;
521
522    return s;
523  }
524
525  /** @This returns maximum container size */
526  size_type max_size() const
527  {
528    return (size_type)(-1);
529  }
530
531  /** @This appends all items from the given list to the end of this list */
532  void append(linked_list &list)
533  {
534    if (!list.empty())
535      {
536        list.m_root.m_prev->m_next = &m_root;
537        list.m_root.m_next->m_prev = m_root.m_prev;
538        m_root.m_prev->m_next = list.m_root.m_next;
539        m_root.m_prev = list.m_root.m_prev;
540        list._empty();
541      }
542  }
543
544  /** @This appends all item from the given list in front of this list */
545  void prepend(linked_list &list)
546  {
547    if (!list.empty())
548      {
549        list.m_root.m_next->m_prev = &m_root;
550        list.m_root.m_prev->m_next = m_root.m_next;
551        m_root.m_next->m_prev = list.m_root.m_prev;
552        m_root.m_next = list.m_root.m_next;
553        list._empty();
554      }
555  }
556
557  /** @This merges with specified ordered list according to specified sort predicate */
558  void merge(linked_list &list, _predicate *func)
559  {
560    _rebuild(_merge(m_root.m_next, list.m_root.m_next, func));
561    list._empty();
562  }
563
564  /** @This merges with specified ordered list using default predicate */
565  void merge(linked_list &list)
566  {
567    merge(list, _default_predicate);
568  }
569
570  /** @This sorts this list according to specified sort predicate */
571  void sort(_predicate *func)
572  {
573    /* Fast linked list stack based merge sort algorithm by Alexandre Becoulet */
574
575    if (m_root.m_prev == m_root.m_next)
576      return;
577
578    unsigned int n = 0;         /* index of current node pair */
579    linked_list_node *tail = m_root.m_next; /* remaining unprocessed nodes */
580    linked_list_node *stack[41]; /* we are able to sort 2^40 nodes here */
581    linked_list_node **s = stack;
582
583    m_root.m_prev->m_next = 0;
584
585    while (tail)
586      {
587        unsigned int idx, tmp;
588
589        /* Pick 2 nodes */
590        linked_list_node *a = tail;
591        linked_list_node *b = tail->m_next;
592
593        if (!b)
594          {
595            *s++ = a;
596            break;
597          }
598
599        tail = b->m_next;
600
601        /* Create a sorted pair list and push it on stack */
602        if (func(static_cast<X&>(static_cast<item_type &>(*a)),
603                 static_cast<X&>(static_cast<item_type &>(*b))))
604          ((*s = a)->m_next = b)->m_next = 0;
605        else
606          ((*s = b)->m_next = a)->m_next = 0;
607
608        s++;
609
610        /* Reduce stack by merging top lists as if we were building a
611           complete binary tree from leaf nodes. We compute needed
612           merge count from bits change in pair index. */
613        tmp = n++;
614        for (idx = n ^ tmp; idx &= idx - 1; s--)
615          s[-2] = _merge(s[-2], s[-1], func);
616      }
617
618    /* Merge all remaining lists */
619    while (s-- > stack + 1)
620      s[-1] = _merge(s[-1], s[0], func);
621
622    /* rebuild prev links and root */
623    _rebuild(stack[0]);
624  }
625
626  /** @This sorts this list using default predicate */
627  void sort()
628  {
629    sort(_default_predicate);
630  }
631
632  /** @This returns a reference to the first list item */
633  X & front() const
634  {
635    return static_cast<X &>(static_cast<item_type &>(*m_root.m_next));
636  }
637
638  /** @This returns a reference to the last list item */
639  X & back() const
640  {
641    return static_cast<X &>(static_cast<item_type &>(*m_root.m_prev));
642  }
643
644  /** @This returns list begin iterator */
645  iterator begin()
646  {
647    return iterator(m_root.m_next);
648  }
649
650  /** @This return list begin const iterator */
651  const_iterator begin() const
652  {
653    return const_iterator(m_root.m_next);
654  }
655
656  /** @This returns list end iterator */
657  iterator end()
658  {
659    return iterator(&m_root);
660  }
661
662  /** @This returns list end const iterator */
663  const_iterator end() const
664  {
665    return const_iterator(&m_root);
666  }
667
668  /** @This returns list begin reverse iterator */
669  reverse_iterator rbegin()
670  {
671    return reverse_iterator(m_root.m_prev);
672  }
673
674  /** @This returns list begin reverse const iterator */
675  const_reverse_iterator rbegin() const
676  {
677    return const_reverse_iterator(m_root.m_prev);
678  }
679
680  /** @This returns list end reverse iterator */
681  reverse_iterator rend()
682  {
683    return reverse_iterator(&m_root);
684  }
685
686  /** @This returns list end reverse const iterator */
687  const_reverse_iterator rend() const
688  {
689    return const_reverse_iterator(&m_root);
690  }
691
692  /** @This clears this list and push a single item */
693  linked_list & operator=(X &i)
694  {
695    clear();
696    push_back(i);
697    return *this;
698  }
699
700  /** @This push an item at the end of this list */
701  linked_list & operator+=(X &i)
702  {
703    push_back(i);
704    return *this;
705  }
706
707  /** @This removes the given item from this list */
708  linked_list & operator-=(X &i)
709  {
710    _remove(static_cast<item_type*>(&i));
711    return *this;
712  }
713};
714
715//////////////////////////////////////////////////////////////////////
716//      linked_list item class
717//////////////////////////////////////////////////////////////////////
718
719/** @internal */
720class linked_list_item_vbase
721{
722public:
723  /* These empty default implementations are defined in a virtual base
724     class to avoid ambiguity when user class inherits from multiple
725     linked_list_item bases */
726  void linked_list_post_remove()
727  {
728  }
729
730  void linked_list_pre_insert()
731  {
732  }
733};
734
735/** @short Linked list item class
736    @module{Linked list container}
737    @header dpp/linked_list
738
739    Item class must inherit from this class to be a valid @ref linked_list item.
740
741    Multiple inheritance with different @tt id values enables items to
742    be part of several distinct linked list containers simultaneously.
743
744    All membership management functions in this class are @tt
745    protected. They may still be selectively exposed publicly in the
746    item class by adding an associated @tt using directive
747    in the @tt public inherited class part.
748*/
749
750template <class X, int id, bool smart>
751class linked_list_item
752  : public linked_list_node
753  , virtual public linked_list_item_vbase
754{
755  template <class, int, bool, class> friend class linked_list;
756  template <class, int, class, bool, bool> friend class linked_list_iterator;
757
758protected:
759  /** Associated list container type */
760  typedef linked_list<X, id, smart> list_type;
761
762private:
763
764  linked_list_item(linked_list_item *next, linked_list_item *prev)
765    : linked_list_node(next, prev)
766  {
767  }
768
769  void _check_not_orphan() const
770  {
771    assert(linked_list_node::m_next != 0 || !"bad operation, item is not part of a linked_list");
772  }
773
774  void _check_orphan()
775  {
776    if (smart)
777      {
778        // smartly remove from current container if any
779        if (linked_list_node::m_next != 0)
780          list_type::_remove(this);
781      }
782    else
783      {
784        assert(linked_list_node::m_next == 0 || !"bad operation, item is currently part of a linked_list");
785      }
786  }
787
788  void _set_orphan()
789  {
790    linked_list_node::m_next = 0;
791  }
792
793protected:
794  typedef linked_list_iterator<X, id, linked_list_node, true, smart> iterator;
795  typedef linked_list_iterator<X, id, const linked_list_node, true, smart> const_iterator;
796
797  /** @This constructs an orphan list item. */
798  linked_list_item()
799  {
800    _set_orphan();
801  }
802
803  ~linked_list_item()
804  {
805    _check_orphan();   
806  }
807
808  /** @This constructs a list item copy. Items copies are orphan. */
809  linked_list_item(const linked_list_item &i)
810  {
811    _set_orphan();
812  }
813
814  /** @This @b preserves list current membership */
815  linked_list_item & operator=(const linked_list_item &i)
816  {
817    // do not change list membership
818    return *this;
819  }
820
821  /** @This tests if item is part of a list */
822  bool orphan()
823  {
824    return linked_list_node::m_next == 0;
825  }
826
827  /** @This exchanges this item with specified item. Both items must
828      be part of a list.
829      @return an iterator to the replacement item.
830  */
831  iterator swap(X &in)
832  {
833    linked_list_item *i = static_cast<linked_list_item*>(&in);
834    _check_not_orphan();
835    i->_check_not_orphan();
836    list_type::_swap(this, i);
837    return iterator(i);
838  }
839
840  /** @This replaces this item in its list by the given orphan item.
841      @return an iterator to the replacement item.
842  */
843  iterator replace(X &in)
844  {
845    linked_list_item *i = static_cast<linked_list_item*>(&in);
846    list_type::_replace(this, static_cast<linked_list_item*>(i));
847    return iterator(i);
848  }
849
850  /** @This removes item from its current list */
851  void remove()
852  {
853    list_type::_remove(this);
854  }
855
856  /** @This inserts an item after this item in the current list */
857  void push_back(linked_list_item &i)
858  {
859    _check_not_orphan();
860    list_type::_insert_post(this, static_cast<linked_list_item*>(&i));
861  }
862
863  /** @This inserts an item before this item in the current list */
864  void push_front(linked_list_item &i)
865  {
866    _check_not_orphan();
867    list_type::_insert_pre(this, static_cast<linked_list_item*>(&i));
868  }
869
870  /** @This returns an iterator to this item in the list */
871  iterator current()
872  {
873    _check_not_orphan();
874    return iterator(this);
875  }
876
877  /** @This returns a const iterator to this item in the list */
878  const_iterator current() const
879  {
880    _check_not_orphan();
881    return const_iterator(this);
882  }
883
884  /** @This returns an iterator to the next item in the list */
885  iterator next()
886  {
887    _check_not_orphan();
888    return iterator(linked_list_node::m_next);
889  }
890
891  /** @This returns a const iterator to the next item in the list */
892  const_iterator next() const
893  {
894    _check_not_orphan();
895    return const_iterator(linked_list_node::m_next);
896  }
897
898  /** @This returns an iterator to the previous item in the list */
899  iterator prev()
900  {
901    _check_not_orphan();
902    return iterator(linked_list_node::m_prev);
903  }
904
905  /** @This returns a const iterator to the previous item in the list */
906  const_iterator prev() const
907  {
908    _check_not_orphan();
909    return const_iterator(linked_list_node::m_prev);
910  }
911
912#ifdef __MKDOC__
913  /* actual definitions are located in the linked_list_item_vbase class */
914
915  /** @This is called when the object has been removed from a linked
916      list. The call is performed on a reference to @tt X class so a
917      virtual prototype must be declared in the @tt X class to
918      override this function from further derived classes. This
919      default implementation is empty. */
920  inline void linked_list_post_remove();
921
922  /** @This is called when the object becomes part of a linked list. The
923      call is performed on a reference to @tt X class so a virtual
924      prototype must be declared in the @tt X class to override this
925      function from further derived classes. This default
926      implementation is empty. */
927  inline void linked_list_pre_insert();
928
929#endif
930
931};
932
933}
934
935#endif
936
Note: See TracBrowser for help on using the repository browser.