# debug/list

Go to the documentation of this file.

    00001 // Debugging list implementation -*- C++ -*-
    00002
    00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    00004 // Free Software Foundation, Inc.
    00005 //
    00006 // This file is part of the GNU ISO C++ Library.  This library is free
    00007 // software; you can redistribute it and/or modify it under the
    00008 // terms of the GNU General Public License as published by the
    00009 // Free Software Foundation; either version 3, or (at your option)
    00010 // any later version.
    00011
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 // GNU General Public License for more details.
    00016
    00017 // Under Section 7 of GPL version 3, you are granted additional
    00018 // permissions described in the GCC Runtime Library Exception, version
    00019 // 3.1, as published by the Free Software Foundation.
    00020
    00021 // You should have received a copy of the GNU General Public License and
    00022 // a copy of the GCC Runtime Library Exception along with this program;
    00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00024 // <http://www.gnu.org/licenses/>.
    00025
    00026 /** @file debug/list
    00027  *  This file is a GNU debug extension to the Standard C++ Library.
    00028  */
    00029
    00030 #ifndef _GLIBCXX_DEBUG_LIST
    00031 #define _GLIBCXX_DEBUG_LIST 1
    00032
    00033 #include <list>
    00034 #include <debug/safe_sequence.h>
    00035 #include <debug/safe_iterator.h>
    00036
    00037 namespace std
    00038 {
    00039 namespace __debug
    00040 {
    00041   /// Class std::list with safety/checking/debug instrumentation.
    00042   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
    00043     class list
    00044     : public _GLIBCXX_STD_D::list<_Tp, _Allocator>,
    00045       public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
    00046     {
    00047       typedef _GLIBCXX_STD_D::list<_Tp, _Allocator> _Base;
    00048       typedef __gnu_debug::_Safe_sequence<list>  _Safe_base;
    00049
    00050     public:
    00051       typedef typename _Base::reference             reference;
    00052       typedef typename _Base::const_reference       const_reference;
    00053
    00054       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, list>
    00055                             iterator;
    00056       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, list>
    00057                             const_iterator;
    00058
    00059       typedef typename _Base::size_type             size_type;
    00060       typedef typename _Base::difference_type       difference_type;
    00061
    00062       typedef _Tp                   value_type;
    00063       typedef _Allocator                allocator_type;
    00064       typedef typename _Base::pointer               pointer;
    00065       typedef typename _Base::const_pointer         const_pointer;
    00066       typedef std::reverse_iterator<iterator>       reverse_iterator;
    00067       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
    00068
    00069       // 23.2.2.1 construct/copy/destroy:
    00070       explicit list(const _Allocator& __a = _Allocator())
    00071       : _Base(__a) { }
    00072
    00073       explicit list(size_type __n, const _Tp& __value = _Tp(),
    00074             const _Allocator& __a = _Allocator())
    00075       : _Base(__n, __value, __a) { }
    00076
    00077       template<class _InputIterator>
    00078       list(_InputIterator __first, _InputIterator __last,
    00079        const _Allocator& __a = _Allocator())
    00080       : _Base(__gnu_debug::__check_valid_range(__first, __last), __last, __a)
    00081       { }
    00082
    00083
    00084       list(const list& __x)
    00085       : _Base(__x), _Safe_base() { }
    00086
    00087       list(const _Base& __x)
    00088       : _Base(__x), _Safe_base() { }
    00089
    00090 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00091       list(list&& __x)
    00092       : _Base(std::forward<list>(__x)), _Safe_base()
    00093       { this->_M_swap(__x); }
    00094
    00095       list(initializer_list<value_type> __l,
    00096            const allocator_type& __a = allocator_type())
    00097         : _Base(__l, __a), _Safe_base() { }
    00098 #endif
    00099
    00100       ~list() { }
    00101
    00102       list&
    00103       operator=(const list& __x)
    00104       {
    00105     static_cast<_Base&>(*this) = __x;
    00106     this->_M_invalidate_all();
    00107     return *this;
    00108       }
    00109
    00110 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00111       list&
    00112       operator=(list&& __x)
    00113       {
    00114     // NB: DR 1204.
    00115     // NB: DR 675.
    00116     clear();
    00117     swap(__x);
    00118         return *this;
    00119       }
    00120
    00121       list&
    00122       operator=(initializer_list<value_type> __l)
    00123       {
    00124     static_cast<_Base&>(*this) = __l;
    00125     this->_M_invalidate_all();
    00126     return *this;
    00127       }
    00128
    00129       void
    00130       assign(initializer_list<value_type> __l)
    00131       {
    00132     _Base::assign(__l);
    00133     this->_M_invalidate_all();
    00134       }
    00135 #endif
    00136
    00137       template<class _InputIterator>
    00138         void
    00139         assign(_InputIterator __first, _InputIterator __last)
    00140         {
    00141       __glibcxx_check_valid_range(__first, __last);
    00142       _Base::assign(__first, __last);
    00143       this->_M_invalidate_all();
    00144     }
    00145
    00146       void
    00147       assign(size_type __n, const _Tp& __t)
    00148       {
    00149     _Base::assign(__n, __t);
    00150     this->_M_invalidate_all();
    00151       }
    00152
    00153       using _Base::get_allocator;
    00154
    00155       // iterators:
    00156       iterator
    00157       begin()
    00158       { return iterator(_Base::begin(), this); }
    00159
    00160       const_iterator
    00161       begin() const
    00162       { return const_iterator(_Base::begin(), this); }
    00163
    00164       iterator
    00165       end()
    00166       { return iterator(_Base::end(), this); }
    00167
    00168       const_iterator
    00169       end() const
    00170       { return const_iterator(_Base::end(), this); }
    00171
    00172       reverse_iterator
    00173       rbegin()
    00174       { return reverse_iterator(end()); }
    00175
    00176       const_reverse_iterator
    00177       rbegin() const
    00178       { return const_reverse_iterator(end()); }
    00179
    00180       reverse_iterator
    00181       rend()
    00182       { return reverse_iterator(begin()); }
    00183
    00184       const_reverse_iterator
    00185       rend() const
    00186       { return const_reverse_iterator(begin()); }
    00187
    00188 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00189       const_iterator
    00190       cbegin() const
    00191       { return const_iterator(_Base::begin(), this); }
    00192
    00193       const_iterator
    00194       cend() const
    00195       { return const_iterator(_Base::end(), this); }
    00196
    00197       const_reverse_iterator
    00198       crbegin() const
    00199       { return const_reverse_iterator(end()); }
    00200
    00201       const_reverse_iterator
    00202       crend() const
    00203       { return const_reverse_iterator(begin()); }
    00204 #endif
    00205
    00206       // 23.2.2.2 capacity:
    00207       using _Base::empty;
    00208       using _Base::size;
    00209       using _Base::max_size;
    00210
    00211       void
    00212       resize(size_type __sz, _Tp __c = _Tp())
    00213       {
    00214     this->_M_detach_singular();
    00215
    00216     // if __sz < size(), invalidate all iterators in [begin+__sz, end())
    00217     iterator __victim = begin();
    00218     iterator __end = end();
    00219     for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
    00220       ++__victim;
    00221
    00222     while (__victim != __end)
    00223       {
    00224         iterator __real_victim = __victim++;
    00225         __real_victim._M_invalidate();
    00226       }
    00227
    00228     __try
    00229       {
    00230         _Base::resize(__sz, __c);
    00231       }
    00232     __catch(...)
    00233       {
    00234         this->_M_revalidate_singular();
    00235         __throw_exception_again;
    00236       }
    00237       }
    00238
    00239       // element access:
    00240       reference
    00241       front()
    00242       {
    00243     __glibcxx_check_nonempty();
    00244     return _Base::front();
    00245       }
    00246
    00247       const_reference
    00248       front() const
    00249       {
    00250     __glibcxx_check_nonempty();
    00251     return _Base::front();
    00252       }
    00253
    00254       reference
    00255       back()
    00256       {
    00257     __glibcxx_check_nonempty();
    00258     return _Base::back();
    00259       }
    00260
    00261       const_reference
    00262       back() const
    00263       {
    00264     __glibcxx_check_nonempty();
    00265     return _Base::back();
    00266       }
    00267
    00268       // 23.2.2.3 modifiers:
    00269       using _Base::push_front;
    00270
    00271 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00272       using _Base::emplace_front;
    00273 #endif
    00274
    00275       void
    00276       pop_front()
    00277       {
    00278     __glibcxx_check_nonempty();
    00279     iterator __victim = begin();
    00280     __victim._M_invalidate();
    00281     _Base::pop_front();
    00282       }
    00283
    00284       using _Base::push_back;
    00285
    00286 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00287       using _Base::emplace_back;
    00288 #endif
    00289
    00290       void
    00291       pop_back()
    00292       {
    00293     __glibcxx_check_nonempty();
    00294     iterator __victim = end();
    00295     --__victim;
    00296     __victim._M_invalidate();
    00297     _Base::pop_back();
    00298       }
    00299
    00300 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00301       template<typename... _Args>
    00302         iterator
    00303         emplace(iterator __position, _Args&&... __args)
    00304     {
    00305       __glibcxx_check_insert(__position);
    00306       return iterator(_Base::emplace(__position.base(),
    00307                     std::forward<_Args>(__args)...), this);
    00308     }
    00309 #endif
    00310
    00311       iterator
    00312       insert(iterator __position, const _Tp& __x)
    00313       {
    00314     __glibcxx_check_insert(__position);
    00315     return iterator(_Base::insert(__position.base(), __x), this);
    00316       }
    00317
    00318 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00319       iterator
    00320       insert(iterator __position, _Tp&& __x)
    00321       { return emplace(__position, std::move(__x)); }
    00322
    00323       void
    00324       insert(iterator __p, initializer_list<value_type> __l)
    00325       {
    00326     __glibcxx_check_insert(__p);
    00327     _Base::insert(__p, __l);
    00328       }
    00329 #endif
    00330
    00331       void
    00332       insert(iterator __position, size_type __n, const _Tp& __x)
    00333       {
    00334     __glibcxx_check_insert(__position);
    00335     _Base::insert(__position.base(), __n, __x);
    00336       }
    00337
    00338       template<class _InputIterator>
    00339         void
    00340         insert(iterator __position, _InputIterator __first,
    00341            _InputIterator __last)
    00342         {
    00343       __glibcxx_check_insert_range(__position, __first, __last);
    00344       _Base::insert(__position.base(), __first, __last);
    00345     }
    00346
    00347       iterator
    00348       erase(iterator __position)
    00349       {
    00350     __glibcxx_check_erase(__position);
    00351     __position._M_invalidate();
    00352     return iterator(_Base::erase(__position.base()), this);
    00353       }
    00354
    00355       iterator
    00356       erase(iterator __position, iterator __last)
    00357       {
    00358     // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00359     // 151. can't currently clear() empty container
    00360     __glibcxx_check_erase_range(__position, __last);
    00361     for (iterator __victim = __position; __victim != __last; )
    00362       {
    00363         iterator __old = __victim;
    00364         ++__victim;
    00365         __old._M_invalidate();
    00366       }
    00367     return iterator(_Base::erase(__position.base(), __last.base()), this);
    00368       }
    00369
    00370       void
    00371       swap(list& __x)
    00372       {
    00373     _Base::swap(__x);
    00374     this->_M_swap(__x);
    00375       }
    00376
    00377       void
    00378       clear()
    00379       {
    00380     _Base::clear();
    00381     this->_M_invalidate_all();
    00382       }
    00383
    00384       // 23.2.2.4 list operations:
    00385       void
    00386 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00387       splice(iterator __position, list&& __x)
    00388 #else
    00389       splice(iterator __position, list& __x)
    00390 #endif
    00391       {
    00392     _GLIBCXX_DEBUG_VERIFY(&__x != this,
    00393                   _M_message(__gnu_debug::__msg_self_splice)
    00394                   ._M_sequence(*this, "this"));
    00395     this->splice(__position, _GLIBCXX_MOVE(__x), __x.begin(), __x.end());
    00396       }
    00397
    00398 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00399       void
    00400       splice(iterator __position, list& __x)
    00401       { splice(__position, std::move(__x)); }
    00402 #endif
    00403
    00404       void
    00405 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00406       splice(iterator __position, list&& __x, iterator __i)
    00407 #else
    00408       splice(iterator __position, list& __x, iterator __i)
    00409 #endif
    00410       {
    00411     __glibcxx_check_insert(__position);
    00412
    00413     // We used to perform the splice_alloc check:  not anymore, redundant
    00414     // after implementing the relevant bits of N1599.
    00415
    00416     _GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(),
    00417                   _M_message(__gnu_debug::__msg_splice_bad)
    00418                   ._M_iterator(__i, "__i"));
    00419     _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x),
    00420                   _M_message(__gnu_debug::__msg_splice_other)
    00421                  ._M_iterator(__i, "__i")._M_sequence(__x, "__x"));
    00422
    00423     // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00424     // 250. splicing invalidates iterators
    00425     this->_M_transfer_iter(__i);
    00426     _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
    00427               __i.base());
    00428       }
    00429
    00430 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00431       void
    00432       splice(iterator __position, list& __x, iterator __i)
    00433       { splice(__position, std::move(__x), __i); }
    00434 #endif
    00435
    00436       void
    00437 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00438       splice(iterator __position, list&& __x, iterator __first,
    00439          iterator __last)
    00440 #else
    00441       splice(iterator __position, list& __x, iterator __first,
    00442          iterator __last)
    00443 #endif
    00444       {
    00445     __glibcxx_check_insert(__position);
    00446     __glibcxx_check_valid_range(__first, __last);
    00447     _GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x),
    00448                   _M_message(__gnu_debug::__msg_splice_other)
    00449                   ._M_sequence(__x, "x")
    00450                   ._M_iterator(__first, "first"));
    00451
    00452     // We used to perform the splice_alloc check:  not anymore, redundant
    00453     // after implementing the relevant bits of N1599.
    00454
    00455     for (iterator __tmp = __first; __tmp != __last; )
    00456       {
    00457         _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position,
    00458                 _M_message(__gnu_debug::__msg_splice_overlap)
    00459                   ._M_iterator(__tmp, "position")
    00460                   ._M_iterator(__first, "first")
    00461                   ._M_iterator(__last, "last"));
    00462         iterator __victim = __tmp++;
    00463         // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00464         // 250. splicing invalidates iterators
    00465         this->_M_transfer_iter(__victim);
    00466       }
    00467
    00468     _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
    00469               __first.base(), __last.base());
    00470       }
    00471
    00472 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00473       void
    00474       splice(iterator __position, list& __x, iterator __first, iterator __last)
    00475       { splice(__position, std::move(__x), __first, __last); }
    00476 #endif
    00477
    00478       void
    00479       remove(const _Tp& __value)
    00480       {
    00481     for (iterator __x = begin(); __x.base() != _Base::end(); )
    00482       {
    00483         if (*__x == __value)
    00484           __x = erase(__x);
    00485         else
    00486           ++__x;
    00487       }
    00488       }
    00489
    00490       template<class _Predicate>
    00491         void
    00492         remove_if(_Predicate __pred)
    00493         {
    00494       for (iterator __x = begin(); __x.base() != _Base::end(); )
    00495         {
    00496           if (__pred(*__x))
    00497         __x = erase(__x);
    00498           else
    00499         ++__x;
    00500         }
    00501     }
    00502
    00503       void
    00504       unique()
    00505       {
    00506     iterator __first = begin();
    00507     iterator __last = end();
    00508     if (__first == __last)
    00509       return;
    00510     iterator __next = __first;
    00511     while (++__next != __last)
    00512       {
    00513         if (*__first == *__next)
    00514           erase(__next);
    00515         else
    00516           __first = __next;
    00517         __next = __first;
    00518       }
    00519       }
    00520
    00521       template<class _BinaryPredicate>
    00522         void
    00523         unique(_BinaryPredicate __binary_pred)
    00524         {
    00525       iterator __first = begin();
    00526       iterator __last = end();
    00527       if (__first == __last)
    00528         return;
    00529       iterator __next = __first;
    00530       while (++__next != __last)
    00531         {
    00532           if (__binary_pred(*__first, *__next))
    00533         erase(__next);
    00534           else
    00535         __first = __next;
    00536           __next = __first;
    00537         }
    00538     }
    00539
    00540       void
    00541 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00542       merge(list&& __x)
    00543 #else
    00544       merge(list& __x)
    00545 #endif
    00546       {
    00547     // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00548     // 300. list::merge() specification incomplete
    00549     if (this != &__x)
    00550       {
    00551         __glibcxx_check_sorted(_Base::begin(), _Base::end());
    00552         __glibcxx_check_sorted(__x.begin().base(), __x.end().base());
    00553         for (iterator __tmp = __x.begin(); __tmp != __x.end();)
    00554           {
    00555         iterator __victim = __tmp++;
    00556         this->_M_transfer_iter(__victim);
    00557           }
    00558         _Base::merge(_GLIBCXX_MOVE(__x._M_base()));
    00559       }
    00560       }
    00561
    00562 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00563       void
    00564       merge(list& __x)
    00565       { merge(std::move(__x)); }
    00566 #endif
    00567
    00568       template<class _Compare>
    00569         void
    00570 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00571         merge(list&& __x, _Compare __comp)
    00572 #else
    00573         merge(list& __x, _Compare __comp)
    00574 #endif
    00575         {
    00576       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00577       // 300. list::merge() specification incomplete
    00578       if (this != &__x)
    00579         {
    00580           __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(),
    00581                       __comp);
    00582           __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(),
    00583                       __comp);
    00584           for (iterator __tmp = __x.begin(); __tmp != __x.end();)
    00585         {
    00586           iterator __victim = __tmp++;
    00587           this->_M_transfer_iter(__victim);
    00588         }
    00589           _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp);
    00590         }
    00591     }
    00592
    00593 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00594       template<typename _Compare>
    00595         void
    00596         merge(list& __x, _Compare __comp)
    00597         { merge(std::move(__x), __comp); }
    00598 #endif
    00599
    00600       void
    00601       sort() { _Base::sort(); }
    00602
    00603       template<typename _StrictWeakOrdering>
    00604         void
    00605         sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
    00606
    00607       using _Base::reverse;
    00608
    00609       _Base&
    00610       _M_base()       { return *this; }
    00611
    00612       const _Base&
    00613       _M_base() const { return *this; }
    00614
    00615     private:
    00616       void
    00617       _M_invalidate_all()
    00618       {
    00619     typedef typename _Base::const_iterator _Base_const_iterator;
    00620     typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
    00621     this->_M_invalidate_if(_Not_equal(_M_base().end()));
    00622       }
    00623     };
    00624
    00625   template<typename _Tp, typename _Alloc>
    00626     inline bool
    00627     operator==(const list<_Tp, _Alloc>& __lhs,
    00628            const list<_Tp, _Alloc>& __rhs)
    00629     { return __lhs._M_base() == __rhs._M_base(); }
    00630
    00631   template<typename _Tp, typename _Alloc>
    00632     inline bool
    00633     operator!=(const list<_Tp, _Alloc>& __lhs,
    00634            const list<_Tp, _Alloc>& __rhs)
    00635     { return __lhs._M_base() != __rhs._M_base(); }
    00636
    00637   template<typename _Tp, typename _Alloc>
    00638     inline bool
    00639     operator<(const list<_Tp, _Alloc>& __lhs,
    00640           const list<_Tp, _Alloc>& __rhs)
    00641     { return __lhs._M_base() < __rhs._M_base(); }
    00642
    00643   template<typename _Tp, typename _Alloc>
    00644     inline bool
    00645     operator<=(const list<_Tp, _Alloc>& __lhs,
    00646            const list<_Tp, _Alloc>& __rhs)
    00647     { return __lhs._M_base() <= __rhs._M_base(); }
    00648
    00649   template<typename _Tp, typename _Alloc>
    00650     inline bool
    00651     operator>=(const list<_Tp, _Alloc>& __lhs,
    00652            const list<_Tp, _Alloc>& __rhs)
    00653     { return __lhs._M_base() >= __rhs._M_base(); }
    00654
    00655   template<typename _Tp, typename _Alloc>
    00656     inline bool
    00657     operator>(const list<_Tp, _Alloc>& __lhs,
    00658           const list<_Tp, _Alloc>& __rhs)
    00659     { return __lhs._M_base() > __rhs._M_base(); }
    00660
    00661   template<typename _Tp, typename _Alloc>
    00662     inline void
    00663     swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
    00664     { __lhs.swap(__rhs); }
    00665
    00666 } // namespace __debug
    00667 } // namespace std
    00668
    00669 #endif