# stl_list.h

Go to the documentation of this file.

    00001 // List implementation -*- C++ -*-
    00002
    00003 // Copyright (C) 2001, 2002 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 2, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License along
    00017 // with this library; see the file COPYING.  If not, write to the Free
    00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    00019 // USA.
    00020
    00021 // As a special exception, you may use this file as part of a free software
    00022 // library without restriction.  Specifically, if other files instantiate
    00023 // templates or use macros or inline functions from this file, or you compile
    00024 // this file and link it with other files to produce an executable, this
    00025 // file does not by itself cause the resulting executable to be covered by
    00026 // the GNU General Public License.  This exception does not however
    00027 // invalidate any other reasons why the executable file might be covered by
    00028 // the GNU General Public License.
    00029
    00030 /*
    00031  *
    00032  * Copyright (c) 1994
    00033  * Hewlett-Packard Company
    00034  *
    00035  * Permission to use, copy, modify, distribute and sell this software
    00036  * and its documentation for any purpose is hereby granted without fee,
    00037  * provided that the above copyright notice appear in all copies and
    00038  * that both that copyright notice and this permission notice appear
    00039  * in supporting documentation.  Hewlett-Packard Company makes no
    00040  * representations about the suitability of this software for any
    00041  * purpose.  It is provided "as is" without express or implied warranty.
    00042  *
    00043  *
    00044  * Copyright (c) 1996,1997
    00045  * Silicon Graphics Computer Systems, Inc.
    00046  *
    00047  * Permission to use, copy, modify, distribute and sell this software
    00048  * and its documentation for any purpose is hereby granted without fee,
    00049  * provided that the above copyright notice appear in all copies and
    00050  * that both that copyright notice and this permission notice appear
    00051  * in supporting documentation.  Silicon Graphics makes no
    00052  * representations about the suitability of this software for any
    00053  * purpose.  It is provided "as is" without express or implied warranty.
    00054  */
    00055
    00061 #ifndef __GLIBCPP_INTERNAL_LIST_H
    00062 #define __GLIBCPP_INTERNAL_LIST_H
    00063
    00064 #include <bits/concept_check.h>
    00065
    00066 namespace std
    00067 {
    00068   // Supporting structures are split into common and templated types; the
    00069   // latter publicly inherits from the former in an effort to reduce code
    00070   // duplication.  This results in some "needless" static_cast'ing later on,
    00071   // but it's all safe downcasting.
    00072
    00074   struct _List_node_base
    00075   {
    00076     _List_node_base* _M_next;
    00077     _List_node_base* _M_prev;
    00078   };
    00079
    00081   template<typename _Tp>
    00082     struct _List_node : public _List_node_base
    00083   {
    00084     _Tp _M_data;
    00085   };
    00086
    00087
    00097   struct _List_iterator_base
    00098   {
    00099     typedef size_t                        size_type;
    00100     typedef ptrdiff_t                     difference_type;
    00101     typedef bidirectional_iterator_tag    iterator_category;
    00102
    00104     _List_node_base* _M_node;
    00105
    00106     _List_iterator_base(_List_node_base* __x)
    00107     : _M_node(__x)
    00108     { }
    00109
    00110     _List_iterator_base()
    00111     { }
    00112
    00114     void
    00115     _M_incr()
    00116     { _M_node = _M_node->_M_next; }
    00117
    00119     void
    00120     _M_decr()
    00121     { _M_node = _M_node->_M_prev; }
    00122
    00123     bool
    00124     operator==(const _List_iterator_base& __x) const
    00125     { return _M_node == __x._M_node; }
    00126
    00127     bool
    00128     operator!=(const _List_iterator_base& __x) const
    00129     { return _M_node != __x._M_node; }
    00130   };
    00131
    00142   template<typename _Tp, typename _Ref, typename _Ptr>
    00143     struct _List_iterator : public _List_iterator_base
    00144   {
    00145     typedef _List_iterator<_Tp,_Tp&,_Tp*>             iterator;
    00146     typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
    00147     typedef _List_iterator<_Tp,_Ref,_Ptr>             _Self;
    00148
    00149     typedef _Tp                                       value_type;
    00150     typedef _Ptr                                      pointer;
    00151     typedef _Ref                                      reference;
    00152     typedef _List_node<_Tp>                           _Node;
    00153
    00154     _List_iterator(_Node* __x)
    00155     : _List_iterator_base(__x)
    00156     { }
    00157
    00158     _List_iterator()
    00159     { }
    00160
    00161     _List_iterator(const iterator& __x)
    00162     : _List_iterator_base(__x._M_node)
    00163     { }
    00164
    00165     reference
    00166     operator*() const
    00167     { return static_cast<_Node*>(_M_node)->_M_data; }
    00168     // Must downcast from List_node_base to _List_node to get to _M_data.
    00169
    00170     pointer
    00171     operator->() const
    00172     { return &(operator*()); }
    00173
    00174     _Self&
    00175     operator++()
    00176     {
    00177       this->_M_incr();
    00178       return *this;
    00179     }
    00180
    00181     _Self
    00182     operator++(int)
    00183     {
    00184       _Self __tmp = *this;
    00185       this->_M_incr();
    00186       return __tmp;
    00187     }
    00188
    00189     _Self&
    00190     operator--()
    00191     {
    00192       this->_M_decr();
    00193       return *this;
    00194     }
    00195
    00196     _Self
    00197     operator--(int)
    00198     {
    00199       _Self __tmp = *this;
    00200       this->_M_decr();
    00201       return __tmp;
    00202     }
    00203   };
    00204
    00205
    00207
    00212   template<typename _Tp, typename _Allocator, bool _IsStatic>
    00213     class _List_alloc_base
    00214   {
    00215   public:
    00216     typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
    00217             allocator_type;
    00218
    00219     allocator_type
    00220     get_allocator() const { return _M_node_allocator; }
    00221
    00222     _List_alloc_base(const allocator_type& __a)
    00223     : _M_node_allocator(__a)
    00224     { }
    00225
    00226   protected:
    00227     _List_node<_Tp>*
    00228     _M_get_node()
    00229     { return _M_node_allocator.allocate(1); }
    00230
    00231     void
    00232     _M_put_node(_List_node<_Tp>* __p)
    00233     { _M_node_allocator.deallocate(__p, 1); }
    00234
    00235     // NOTA BENE
    00236     // The stored instance is not actually of "allocator_type"'s type.  Instead
    00237     // we rebind the type to Allocator<List_node<Tp>>, which according to
    00238     // [20.1.5]/4 should probably be the same.  List_node<Tp> is not the same
    00239     // size as Tp (it's two pointers larger), and specializations on Tp may go
    00240     // unused because List_node<Tp> is being bound instead.
    00241     //
    00242     // We put this to the test in get_allocator above; if the two types are
    00243     // actually different, there had better be a conversion between them.
    00244     //
    00245     // None of the predefined allocators shipped with the library (as of 3.1)
    00246     // use this instantiation anyhow; they're all instanceless.
    00247     typename _Alloc_traits<_List_node<_Tp>, _Allocator>::allocator_type
    00248              _M_node_allocator;
    00249
    00250     _List_node<_Tp>* _M_node;
    00251   };
    00252
    00254   template<typename _Tp, typename _Allocator>
    00255     class _List_alloc_base<_Tp, _Allocator, true>
    00256   {
    00257   public:
    00258     typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
    00259             allocator_type;
    00260
    00261     allocator_type
    00262     get_allocator() const { return allocator_type(); }
    00263
    00264     _List_alloc_base(const allocator_type&)
    00265     { }
    00266
    00267   protected:
    00268     // See comment in primary template class about why this is safe for the
    00269     // standard predefined classes.
    00270     typedef typename _Alloc_traits<_List_node<_Tp>, _Allocator>::_Alloc_type
    00271             _Alloc_type;
    00272
    00273     _List_node<_Tp>*
    00274     _M_get_node()
    00275     { return _Alloc_type::allocate(1); }
    00276
    00277     void
    00278     _M_put_node(_List_node<_Tp>* __p)
    00279     { _Alloc_type::deallocate(__p, 1); }
    00280
    00281     _List_node<_Tp>* _M_node;
    00282   };
    00283
    00284
    00290   template <typename _Tp, typename _Alloc>
    00291     class _List_base
    00292     : public _List_alloc_base<_Tp, _Alloc,
    00293                               _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
    00294   {
    00295   public:
    00296     typedef _List_alloc_base<_Tp, _Alloc,
    00297                              _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
    00298             _Base;
    00299     typedef typename _Base::allocator_type allocator_type;
    00300
    00301     _List_base(const allocator_type& __a)
    00302     : _Base(__a)
    00303     {
    00304       _M_node = _M_get_node();
    00305       _M_node->_M_next = _M_node;
    00306       _M_node->_M_prev = _M_node;
    00307     }
    00308
    00309     // This is what actually destroys the list.
    00310     ~_List_base()
    00311     {
    00312       __clear();
    00313       _M_put_node(_M_node);
    00314     }
    00315
    00316     void
    00317     __clear();
    00318   };
    00319
    00320
    00365   template<typename _Tp, typename _Alloc = allocator<_Tp> >
    00366     class list : protected _List_base<_Tp, _Alloc>
    00367   {
    00368     // concept requirements
    00369     __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
    00370
    00371     typedef _List_base<_Tp, _Alloc>                       _Base;
    00372
    00373   public:
    00374     typedef _Tp                                           value_type;
    00375     typedef value_type*                                   pointer;
    00376     typedef const value_type*                             const_pointer;
    00377     typedef _List_iterator<_Tp,_Tp&,_Tp*>                 iterator;
    00378     typedef _List_iterator<_Tp,const _Tp&,const _Tp*>     const_iterator;
    00379     typedef std::reverse_iterator<const_iterator>     const_reverse_iterator;
    00380     typedef std::reverse_iterator<iterator>                 reverse_iterator;
    00381     typedef value_type&                                   reference;
    00382     typedef const value_type&                             const_reference;
    00383     typedef size_t                                        size_type;
    00384     typedef ptrdiff_t                                     difference_type;
    00385     typedef typename _Base::allocator_type                allocator_type;
    00386
    00387   protected:
    00388     // Note that pointers-to-_Node's can be ctor-converted to iterator types.
    00389     typedef _List_node<_Tp>                               _Node;
    00390
    00397     using _Base::_M_node;
    00398     using _Base::_M_put_node;
    00399     using _Base::_M_get_node;
    00400
    00408     _Node*
    00409     _M_create_node(const value_type& __x)
    00410     {
    00411       _Node* __p = _M_get_node();
    00412       try {
    00413         _Construct(&__p->_M_data, __x);
    00414       }
    00415       catch(...)
    00416       {
    00417         _M_put_node(__p);
    00418         __throw_exception_again;
    00419       }
    00420       return __p;
    00421     }
    00422
    00429     _Node*
    00430     _M_create_node()
    00431     {
    00432       _Node* __p = _M_get_node();
    00433       try {
    00434         _Construct(&__p->_M_data);
    00435       }
    00436       catch(...)
    00437       {
    00438         _M_put_node(__p);
    00439         __throw_exception_again;
    00440       }
    00441       return __p;
    00442     }
    00443
    00444   public:
    00445     // [23.2.2.1] construct/copy/destroy
    00446     // (assign() and get_allocator() are also listed in this section)
    00450     explicit
    00451     list(const allocator_type& __a = allocator_type())
    00452     : _Base(__a) { }
    00453
    00461     list(size_type __n, const value_type& __value,
    00462          const allocator_type& __a = allocator_type())
    00463       : _Base(__a)
    00464       { this->insert(begin(), __n, __value); }
    00465
    00473     explicit
    00474     list(size_type __n)
    00475       : _Base(allocator_type())
    00476       { this->insert(begin(), __n, value_type()); }
    00477
    00485     list(const list& __x)
    00486       : _Base(__x.get_allocator())
    00487       { this->insert(begin(), __x.begin(), __x.end()); }
    00488
    00502     template<typename _InputIterator>
    00503       list(_InputIterator __first, _InputIterator __last,
    00504            const allocator_type& __a = allocator_type())
    00505       : _Base(__a)
    00506       { this->insert(begin(), __first, __last); }
    00507
    00513     ~list() { }
    00514
    00522     list&
    00523     operator=(const list& __x);
    00524
    00535     void
    00536     assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
    00537
    00550     template<typename _InputIterator>
    00551       void
    00552       assign(_InputIterator __first, _InputIterator __last)
    00553       {
    00554         // Check whether it's an integral type.  If so, it's not an iterator.
    00555         typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
    00556         _M_assign_dispatch(__first, __last, _Integral());
    00557       }
    00558
    00560     allocator_type
    00561     get_allocator() const { return _Base::get_allocator(); }
    00562
    00563     // iterators
    00568     iterator
    00569     begin() { return static_cast<_Node*>(_M_node->_M_next); }
    00570
    00575     const_iterator
    00576     begin() const { return static_cast<_Node*>(_M_node->_M_next); }
    00577
    00582     iterator
    00583     end() { return _M_node; }
    00584
    00589     const_iterator
    00590     end() const { return _M_node; }
    00591
    00596     reverse_iterator
    00597     rbegin() { return reverse_iterator(end()); }
    00598
    00603     const_reverse_iterator
    00604     rbegin() const { return const_reverse_iterator(end()); }
    00605
    00611     reverse_iterator
    00612     rend() { return reverse_iterator(begin()); }
    00613
    00619     const_reverse_iterator
    00620     rend() const
    00621     { return const_reverse_iterator(begin()); }
    00622
    00623     // [23.2.2.2] capacity
    00627     bool
    00628     empty() const { return _M_node->_M_next == _M_node; }
    00629
    00631     size_type
    00632     size() const { return distance(begin(), end()); }
    00633
    00635     size_type
    00636     max_size() const { return size_type(-1); }
    00637
    00648     void
    00649     resize(size_type __new_size, const value_type& __x);
    00650
    00660     void
    00661     resize(size_type __new_size) { this->resize(__new_size, value_type()); }
    00662
    00663     // element access
    00668     reference
    00669     front() { return *begin(); }
    00670
    00675     const_reference
    00676     front() const { return *begin(); }
    00677
    00682     reference
    00683     back() { return *(--end()); }
    00684
    00689     const_reference
    00690     back() const { return *(--end()); }
    00691
    00692     // [23.2.2.3] modifiers
    00702     void
    00703     push_front(const value_type& __x) { this->insert(begin(), __x); }
    00704
    00705   #ifdef _GLIBCPP_DEPRECATED
    00706
    00718     void
    00719     push_front() { this->insert(begin(), value_type()); }
    00720   #endif
    00721
    00733     void
    00734     pop_front() { this->erase(begin()); }
    00735
    00745     void
    00746     push_back(const value_type& __x) { this->insert(end(), __x); }
    00747
    00748   #ifdef _GLIBCPP_DEPRECATED
    00749
    00761     void
    00762     push_back() { this->insert(end(), value_type()); }
    00763   #endif
    00764
    00776     void
    00777     pop_back()
    00778     {
    00779       iterator __tmp = end();
    00780       this->erase(--__tmp);
    00781     }
    00782
    00794     iterator
    00795     insert(iterator __position, const value_type& __x);
    00796
    00797   #ifdef _GLIBCPP_DEPRECATED
    00798
    00813     iterator
    00814     insert(iterator __position) { return insert(__position, value_type()); }
    00815   #endif
    00816
    00829     void
    00830     insert(iterator __pos, size_type __n, const value_type& __x)
    00831     { _M_fill_insert(__pos, __n, __x); }
    00832
    00845     template<typename _InputIterator>
    00846       void
    00847       insert(iterator __pos, _InputIterator __first, _InputIterator __last)
    00848       {
    00849         // Check whether it's an integral type.  If so, it's not an iterator.
    00850         typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
    00851         _M_insert_dispatch(__pos, __first, __last, _Integral());
    00852       }
    00853
    00870     iterator
    00871     erase(iterator __position);
    00872
    00892     iterator
    00893     erase(iterator __first, iterator __last)
    00894     {
    00895       while (__first != __last)
    00896         erase(__first++);
    00897       return __last;
    00898     }
    00899
    00909     void
    00910     swap(list& __x) { std::swap(_M_node, __x._M_node); }
    00911
    00918     void
    00919     clear() { _Base::__clear(); }
    00920
    00921     // [23.2.2.4] list operations
    00925     void
    00926     splice(iterator __position, list& __x)
    00927     {
    00928       if (!__x.empty())
    00929         this->_M_transfer(__position, __x.begin(), __x.end());
    00930     }
    00931
    00935     void
    00936     splice(iterator __position, list&, iterator __i)
    00937     {
    00938       iterator __j = __i;
    00939       ++__j;
    00940       if (__position == __i || __position == __j) return;
    00941       this->_M_transfer(__position, __i, __j);
    00942     }
    00943
    00947     void
    00948     splice(iterator __position, list&, iterator __first, iterator __last)
    00949     {
    00950       if (__first != __last)
    00951         this->_M_transfer(__position, __first, __last);
    00952     }
    00953
    00957     void
    00958     remove(const _Tp& __value);
    00959
    00963     template<typename _Predicate>
    00964       void
    00965       remove_if(_Predicate);
    00966
    00970     void
    00971     unique();
    00972
    00976     template<typename _BinaryPredicate>
    00977       void
    00978       unique(_BinaryPredicate);
    00979
    00983     void
    00984     merge(list& __x);
    00985
    00989     template<typename _StrictWeakOrdering>
    00990       void
    00991       merge(list&, _StrictWeakOrdering);
    00992
    00996     void
    00997     reverse() { __List_base_reverse(this->_M_node); }
    00998
    01002     void
    01003     sort();
    01004
    01008     template<typename _StrictWeakOrdering>
    01009       void
    01010       sort(_StrictWeakOrdering);
    01011
    01012   protected:
    01013     // Internal assign functions follow.
    01014
    01015     // called by the range assign to implement [23.1.1]/9
    01016     template<typename _Integer>
    01017       void
    01018       _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
    01019       {
    01020         _M_fill_assign(static_cast<size_type>(__n),
    01021                        static_cast<value_type>(__val));
    01022       }
    01023
    01024     // called by the range assign to implement [23.1.1]/9
    01025     template<typename _InputIter>
    01026       void
    01027       _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type);
    01028
    01029     // Called by assign(n,t), and the range assign when it turns out to be the
    01030     // same thing.
    01031     void
    01032     _M_fill_assign(size_type __n, const value_type& __val);
    01033
    01034
    01035     // Internal insert functions follow.
    01036
    01037     // called by the range insert to implement [23.1.1]/9
    01038     template<typename _Integer>
    01039       void
    01040       _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x,
    01041                          __true_type)
    01042       {
    01043         _M_fill_insert(__pos, static_cast<size_type>(__n),
    01044                        static_cast<value_type>(__x));
    01045       }
    01046
    01047     // called by the range insert to implement [23.1.1]/9
    01048     template<typename _InputIterator>
    01049       void
    01050       _M_insert_dispatch(iterator __pos,
    01051                          _InputIterator __first, _InputIterator __last,
    01052                          __false_type)
    01053       {
    01054         for ( ; __first != __last; ++__first)
    01055           insert(__pos, *__first);
    01056       }
    01057
    01058     // Called by insert(p,n,x), and the range insert when it turns out to be
    01059     // the same thing.
    01060     void
    01061     _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
    01062     {
    01063       for ( ; __n > 0; --__n)
    01064         insert(__pos, __x);
    01065     }
    01066
    01067
    01068     // Moves the elements from [first,last) before position.
    01069     void
    01070     _M_transfer(iterator __position, iterator __first, iterator __last)
    01071     {
    01072       if (__position != __last) {
    01073         // Remove [first, last) from its old position.
    01074         __last._M_node->_M_prev->_M_next     = __position._M_node;
    01075         __first._M_node->_M_prev->_M_next    = __last._M_node;
    01076         __position._M_node->_M_prev->_M_next = __first._M_node;
    01077
    01078         // Splice [first, last) into its new position.
    01079         _List_node_base* __tmp      = __position._M_node->_M_prev;
    01080         __position._M_node->_M_prev = __last._M_node->_M_prev;
    01081         __last._M_node->_M_prev     = __first._M_node->_M_prev;
    01082         __first._M_node->_M_prev    = __tmp;
    01083       }
    01084     }
    01085   };
    01086
    01087
    01098   template<typename _Tp, typename _Alloc>
    01099   inline bool
    01100     operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
    01101     {
    01102       typedef typename list<_Tp,_Alloc>::const_iterator const_iterator;
    01103       const_iterator __end1 = __x.end();
    01104       const_iterator __end2 = __y.end();
    01105
    01106       const_iterator __i1 = __x.begin();
    01107       const_iterator __i2 = __y.begin();
    01108       while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) {
    01109         ++__i1;
    01110         ++__i2;
    01111       }
    01112       return __i1 == __end1 && __i2 == __end2;
    01113     }
    01114
    01126   template<typename _Tp, typename _Alloc>
    01127     inline bool
    01128     operator<(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
    01129     {
    01130       return lexicographical_compare(__x.begin(), __x.end(),
    01131                                      __y.begin(), __y.end());
    01132     }
    01133
    01135   template<typename _Tp, typename _Alloc>
    01136     inline bool
    01137     operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
    01138     { return !(__x == __y); }
    01139
    01141   template<typename _Tp, typename _Alloc>
    01142     inline bool
    01143     operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
    01144     { return __y < __x; }
    01145
    01147   template<typename _Tp, typename _Alloc>
    01148     inline bool
    01149     operator<=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
    01150     { return !(__y < __x); }
    01151
    01153   template<typename _Tp, typename _Alloc>
    01154     inline bool
    01155     operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
    01156     { return !(__x < __y); }
    01157
    01159   template<typename _Tp, typename _Alloc>
    01160     inline void
    01161     swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
    01162     { __x.swap(__y); }
    01163 } // namespace std
    01164
    01165 #endif /* __GLIBCPP_INTERNAL_LIST_H */