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
00071       list(const _Allocator& __a = _Allocator())
00072       : _Base(__a) { }
00073 
00074 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00075       explicit
00076       list(size_type __n)
00077       : _Base(__n) { }
00078 
00079       list(size_type __n, const _Tp& __value,
00080        const _Allocator& __a = _Allocator())
00081       : _Base(__n, __value, __a) { }
00082 #else
00083       explicit
00084       list(size_type __n, const _Tp& __value = _Tp(),
00085        const _Allocator& __a = _Allocator())
00086       : _Base(__n, __value, __a) { }
00087 #endif
00088 
00089       template<class _InputIterator>
00090       list(_InputIterator __first, _InputIterator __last,
00091        const _Allocator& __a = _Allocator())
00092       : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
00093                                    __last)),
00094               __gnu_debug::__base(__last), __a)
00095       { }
00096 
00097 
00098       list(const list& __x)
00099       : _Base(__x), _Safe_base() { }
00100 
00101       list(const _Base& __x)
00102       : _Base(__x), _Safe_base() { }
00103 
00104 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00105       list(list&& __x)
00106       : _Base(std::move(__x)), _Safe_base()
00107       { this->_M_swap(__x); }
00108 
00109       list(initializer_list<value_type> __l,
00110            const allocator_type& __a = allocator_type())
00111         : _Base(__l, __a), _Safe_base() { }
00112 #endif
00113 
00114       ~list() { }
00115 
00116       list&
00117       operator=(const list& __x)
00118       {
00119     static_cast<_Base&>(*this) = __x;
00120     this->_M_invalidate_all();
00121     return *this;
00122       }
00123 
00124 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00125       list&
00126       operator=(list&& __x)
00127       {
00128     // NB: DR 1204.
00129     // NB: DR 675.
00130     clear();
00131     swap(__x);
00132         return *this;
00133       }
00134 
00135       list&
00136       operator=(initializer_list<value_type> __l)
00137       {
00138     static_cast<_Base&>(*this) = __l;
00139     this->_M_invalidate_all();
00140     return *this;
00141       }
00142 
00143       void
00144       assign(initializer_list<value_type> __l)
00145       {
00146     _Base::assign(__l);
00147     this->_M_invalidate_all();
00148       }
00149 #endif
00150 
00151       template<class _InputIterator>
00152         void
00153         assign(_InputIterator __first, _InputIterator __last)
00154         {
00155       __glibcxx_check_valid_range(__first, __last);
00156       _Base::assign(__gnu_debug::__base(__first),
00157             __gnu_debug::__base(__last));
00158       this->_M_invalidate_all();
00159     }
00160 
00161       void
00162       assign(size_type __n, const _Tp& __t)
00163       {
00164     _Base::assign(__n, __t);
00165     this->_M_invalidate_all();
00166       }
00167 
00168       using _Base::get_allocator;
00169 
00170       // iterators:
00171       iterator
00172       begin()
00173       { return iterator(_Base::begin(), this); }
00174 
00175       const_iterator
00176       begin() const
00177       { return const_iterator(_Base::begin(), this); }
00178 
00179       iterator
00180       end()
00181       { return iterator(_Base::end(), this); }
00182 
00183       const_iterator
00184       end() const
00185       { return const_iterator(_Base::end(), this); }
00186 
00187       reverse_iterator
00188       rbegin()
00189       { return reverse_iterator(end()); }
00190 
00191       const_reverse_iterator
00192       rbegin() const
00193       { return const_reverse_iterator(end()); }
00194 
00195       reverse_iterator
00196       rend()
00197       { return reverse_iterator(begin()); }
00198 
00199       const_reverse_iterator
00200       rend() const
00201       { return const_reverse_iterator(begin()); }
00202 
00203 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00204       const_iterator
00205       cbegin() const
00206       { return const_iterator(_Base::begin(), this); }
00207 
00208       const_iterator
00209       cend() const
00210       { return const_iterator(_Base::end(), this); }
00211 
00212       const_reverse_iterator
00213       crbegin() const
00214       { return const_reverse_iterator(end()); }
00215 
00216       const_reverse_iterator
00217       crend() const
00218       { return const_reverse_iterator(begin()); }
00219 #endif
00220 
00221       // 23.2.2.2 capacity:
00222       using _Base::empty;
00223       using _Base::size;
00224       using _Base::max_size;
00225 
00226 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00227       void
00228       resize(size_type __sz)
00229       {
00230     this->_M_detach_singular();
00231 
00232     // if __sz < size(), invalidate all iterators in [begin+__sz, end())
00233     iterator __victim = begin();
00234     iterator __end = end();
00235     for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
00236       ++__victim;
00237 
00238     while (__victim != __end)
00239       {
00240         iterator __real_victim = __victim++;
00241         __real_victim._M_invalidate();
00242       }
00243 
00244     __try
00245       {
00246         _Base::resize(__sz);
00247       }
00248     __catch(...)
00249       {
00250         this->_M_revalidate_singular();
00251         __throw_exception_again;
00252       }
00253       }
00254 
00255       void
00256       resize(size_type __sz, const _Tp& __c)
00257       {
00258     this->_M_detach_singular();
00259 
00260     // if __sz < size(), invalidate all iterators in [begin+__sz, end())
00261     iterator __victim = begin();
00262     iterator __end = end();
00263     for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
00264       ++__victim;
00265 
00266     while (__victim != __end)
00267       {
00268         iterator __real_victim = __victim++;
00269         __real_victim._M_invalidate();
00270       }
00271 
00272     __try
00273       {
00274         _Base::resize(__sz, __c);
00275       }
00276     __catch(...)
00277       {
00278         this->_M_revalidate_singular();
00279         __throw_exception_again;
00280       }
00281       }
00282 #else
00283       void
00284       resize(size_type __sz, _Tp __c = _Tp())
00285       {
00286     this->_M_detach_singular();
00287 
00288     // if __sz < size(), invalidate all iterators in [begin+__sz, end())
00289     iterator __victim = begin();
00290     iterator __end = end();
00291     for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
00292       ++__victim;
00293 
00294     while (__victim != __end)
00295       {
00296         iterator __real_victim = __victim++;
00297         __real_victim._M_invalidate();
00298       }
00299 
00300     __try
00301       {
00302         _Base::resize(__sz, __c);
00303       }
00304     __catch(...)
00305       {
00306         this->_M_revalidate_singular();
00307         __throw_exception_again;
00308       }
00309       }
00310 #endif
00311 
00312       // element access:
00313       reference
00314       front()
00315       {
00316     __glibcxx_check_nonempty();
00317     return _Base::front();
00318       }
00319 
00320       const_reference
00321       front() const
00322       {
00323     __glibcxx_check_nonempty();
00324     return _Base::front();
00325       }
00326 
00327       reference
00328       back()
00329       {
00330     __glibcxx_check_nonempty();
00331     return _Base::back();
00332       }
00333 
00334       const_reference
00335       back() const
00336       {
00337     __glibcxx_check_nonempty();
00338     return _Base::back();
00339       }
00340 
00341       // 23.2.2.3 modifiers:
00342       using _Base::push_front;
00343 
00344 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00345       using _Base::emplace_front;
00346 #endif
00347 
00348       void
00349       pop_front()
00350       {
00351     __glibcxx_check_nonempty();
00352     iterator __victim = begin();
00353     __victim._M_invalidate();
00354     _Base::pop_front();
00355       }
00356 
00357       using _Base::push_back;
00358 
00359 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00360       using _Base::emplace_back;
00361 #endif
00362 
00363       void
00364       pop_back()
00365       {
00366     __glibcxx_check_nonempty();
00367     iterator __victim = end();
00368     --__victim;
00369     __victim._M_invalidate();
00370     _Base::pop_back();
00371       }
00372 
00373 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00374       template<typename... _Args>
00375         iterator
00376         emplace(iterator __position, _Args&&... __args)
00377     {
00378       __glibcxx_check_insert(__position);
00379       return iterator(_Base::emplace(__position.base(),
00380                     std::forward<_Args>(__args)...), this);
00381     }
00382 #endif
00383 
00384       iterator
00385       insert(iterator __position, const _Tp& __x)
00386       {
00387     __glibcxx_check_insert(__position);
00388     return iterator(_Base::insert(__position.base(), __x), this);
00389       }
00390 
00391 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00392       iterator
00393       insert(iterator __position, _Tp&& __x)
00394       { return emplace(__position, std::move(__x)); }
00395 
00396       void
00397       insert(iterator __p, initializer_list<value_type> __l)
00398       {
00399     __glibcxx_check_insert(__p);
00400     _Base::insert(__p, __l);
00401       }
00402 #endif
00403 
00404       void
00405       insert(iterator __position, size_type __n, const _Tp& __x)
00406       {
00407     __glibcxx_check_insert(__position);
00408     _Base::insert(__position.base(), __n, __x);
00409       }
00410 
00411       template<class _InputIterator>
00412         void
00413         insert(iterator __position, _InputIterator __first,
00414            _InputIterator __last)
00415         {
00416       __glibcxx_check_insert_range(__position, __first, __last);
00417       _Base::insert(__position.base(), __gnu_debug::__base(__first),
00418                        __gnu_debug::__base(__last));
00419     }
00420 
00421       iterator
00422       erase(iterator __position)
00423       {
00424     __glibcxx_check_erase(__position);
00425     __position._M_invalidate();
00426     return iterator(_Base::erase(__position.base()), this);
00427       }
00428 
00429       iterator
00430       erase(iterator __position, iterator __last)
00431       {
00432     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00433     // 151. can't currently clear() empty container
00434     __glibcxx_check_erase_range(__position, __last);
00435     for (iterator __victim = __position; __victim != __last; )
00436       {
00437         iterator __old = __victim;
00438         ++__victim;
00439         __old._M_invalidate();
00440       }
00441     return iterator(_Base::erase(__position.base(), __last.base()), this);
00442       }
00443 
00444       void
00445       swap(list& __x)
00446       {
00447     _Base::swap(__x);
00448     this->_M_swap(__x);
00449       }
00450 
00451       void
00452       clear()
00453       {
00454     _Base::clear();
00455     this->_M_invalidate_all();
00456       }
00457 
00458       // 23.2.2.4 list operations:
00459       void
00460 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00461       splice(iterator __position, list&& __x)
00462 #else
00463       splice(iterator __position, list& __x)
00464 #endif
00465       {
00466     _GLIBCXX_DEBUG_VERIFY(&__x != this,
00467                   _M_message(__gnu_debug::__msg_self_splice)
00468                   ._M_sequence(*this, "this"));
00469     this->splice(__position, _GLIBCXX_MOVE(__x), __x.begin(), __x.end());
00470       }
00471 
00472 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00473       void
00474       splice(iterator __position, list& __x)
00475       { splice(__position, std::move(__x)); }
00476 #endif
00477 
00478       void
00479 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00480       splice(iterator __position, list&& __x, iterator __i)
00481 #else
00482       splice(iterator __position, list& __x, iterator __i)
00483 #endif
00484       {
00485     __glibcxx_check_insert(__position);
00486 
00487     // We used to perform the splice_alloc check:  not anymore, redundant
00488     // after implementing the relevant bits of N1599.
00489 
00490     _GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(),
00491                   _M_message(__gnu_debug::__msg_splice_bad)
00492                   ._M_iterator(__i, "__i"));
00493     _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x),
00494                   _M_message(__gnu_debug::__msg_splice_other)
00495                  ._M_iterator(__i, "__i")._M_sequence(__x, "__x"));
00496 
00497     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00498     // 250. splicing invalidates iterators
00499     this->_M_transfer_iter(__i);
00500     _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
00501               __i.base());
00502       }
00503 
00504 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00505       void
00506       splice(iterator __position, list& __x, iterator __i)
00507       { splice(__position, std::move(__x), __i); }
00508 #endif
00509 
00510       void
00511 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00512       splice(iterator __position, list&& __x, iterator __first,
00513          iterator __last)
00514 #else
00515       splice(iterator __position, list& __x, iterator __first,
00516          iterator __last)
00517 #endif
00518       {
00519     __glibcxx_check_insert(__position);
00520     __glibcxx_check_valid_range(__first, __last);
00521     _GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x),
00522                   _M_message(__gnu_debug::__msg_splice_other)
00523                   ._M_sequence(__x, "x")
00524                   ._M_iterator(__first, "first"));
00525 
00526     // We used to perform the splice_alloc check:  not anymore, redundant
00527     // after implementing the relevant bits of N1599.
00528 
00529     for (iterator __tmp = __first; __tmp != __last; )
00530       {
00531         _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position,
00532                 _M_message(__gnu_debug::__msg_splice_overlap)
00533                   ._M_iterator(__tmp, "position")
00534                   ._M_iterator(__first, "first")
00535                   ._M_iterator(__last, "last"));
00536         iterator __victim = __tmp++;
00537         // _GLIBCXX_RESOLVE_LIB_DEFECTS
00538         // 250. splicing invalidates iterators
00539         this->_M_transfer_iter(__victim);
00540       }
00541 
00542     _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
00543               __first.base(), __last.base());
00544       }
00545 
00546 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00547       void
00548       splice(iterator __position, list& __x, iterator __first, iterator __last)
00549       { splice(__position, std::move(__x), __first, __last); }
00550 #endif
00551 
00552       void
00553       remove(const _Tp& __value)
00554       {
00555     for (iterator __x = begin(); __x.base() != _Base::end(); )
00556       {
00557         if (*__x == __value)
00558           __x = erase(__x);
00559         else
00560           ++__x;
00561       }
00562       }
00563 
00564       template<class _Predicate>
00565         void
00566         remove_if(_Predicate __pred)
00567         {
00568       for (iterator __x = begin(); __x.base() != _Base::end(); )
00569         {
00570           if (__pred(*__x))
00571         __x = erase(__x);
00572           else
00573         ++__x;
00574         }
00575     }
00576 
00577       void
00578       unique()
00579       {
00580     iterator __first = begin();
00581     iterator __last = end();
00582     if (__first == __last)
00583       return;
00584     iterator __next = __first;
00585     while (++__next != __last)
00586       {
00587         if (*__first == *__next)
00588           erase(__next);
00589         else
00590           __first = __next;
00591         __next = __first;
00592       }
00593       }
00594 
00595       template<class _BinaryPredicate>
00596         void
00597         unique(_BinaryPredicate __binary_pred)
00598         {
00599       iterator __first = begin();
00600       iterator __last = end();
00601       if (__first == __last)
00602         return;
00603       iterator __next = __first;
00604       while (++__next != __last)
00605         {
00606           if (__binary_pred(*__first, *__next))
00607         erase(__next);
00608           else
00609         __first = __next;
00610           __next = __first;
00611         }
00612     }
00613 
00614       void
00615 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00616       merge(list&& __x)
00617 #else
00618       merge(list& __x)
00619 #endif
00620       {
00621     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00622     // 300. list::merge() specification incomplete
00623     if (this != &__x)
00624       {
00625         __glibcxx_check_sorted(_Base::begin(), _Base::end());
00626         __glibcxx_check_sorted(__x.begin().base(), __x.end().base());
00627         for (iterator __tmp = __x.begin(); __tmp != __x.end();)
00628           {
00629         iterator __victim = __tmp++;
00630         this->_M_transfer_iter(__victim);
00631           }
00632         _Base::merge(_GLIBCXX_MOVE(__x._M_base()));
00633       }
00634       }
00635 
00636 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00637       void
00638       merge(list& __x)
00639       { merge(std::move(__x)); }
00640 #endif
00641 
00642       template<class _Compare>
00643         void
00644 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00645         merge(list&& __x, _Compare __comp)
00646 #else
00647         merge(list& __x, _Compare __comp)
00648 #endif
00649         {
00650       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00651       // 300. list::merge() specification incomplete
00652       if (this != &__x)
00653         {
00654           __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(),
00655                       __comp);
00656           __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(),
00657                       __comp);
00658           for (iterator __tmp = __x.begin(); __tmp != __x.end();)
00659         {
00660           iterator __victim = __tmp++;
00661           this->_M_transfer_iter(__victim);
00662         }
00663           _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp);
00664         }
00665     }
00666 
00667 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00668       template<typename _Compare>
00669         void
00670         merge(list& __x, _Compare __comp)
00671         { merge(std::move(__x), __comp); }
00672 #endif
00673 
00674       void
00675       sort() { _Base::sort(); }
00676 
00677       template<typename _StrictWeakOrdering>
00678         void
00679         sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
00680 
00681       using _Base::reverse;
00682 
00683       _Base&
00684       _M_base()       { return *this; }
00685 
00686       const _Base&
00687       _M_base() const { return *this; }
00688 
00689     private:
00690       void
00691       _M_invalidate_all()
00692       {
00693     typedef typename _Base::const_iterator _Base_const_iterator;
00694     typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
00695     this->_M_invalidate_if(_Not_equal(_M_base().end()));
00696       }
00697     };
00698 
00699   template<typename _Tp, typename _Alloc>
00700     inline bool
00701     operator==(const list<_Tp, _Alloc>& __lhs,
00702            const list<_Tp, _Alloc>& __rhs)
00703     { return __lhs._M_base() == __rhs._M_base(); }
00704 
00705   template<typename _Tp, typename _Alloc>
00706     inline bool
00707     operator!=(const list<_Tp, _Alloc>& __lhs,
00708            const list<_Tp, _Alloc>& __rhs)
00709     { return __lhs._M_base() != __rhs._M_base(); }
00710 
00711   template<typename _Tp, typename _Alloc>
00712     inline bool
00713     operator<(const list<_Tp, _Alloc>& __lhs,
00714           const list<_Tp, _Alloc>& __rhs)
00715     { return __lhs._M_base() < __rhs._M_base(); }
00716 
00717   template<typename _Tp, typename _Alloc>
00718     inline bool
00719     operator<=(const list<_Tp, _Alloc>& __lhs,
00720            const list<_Tp, _Alloc>& __rhs)
00721     { return __lhs._M_base() <= __rhs._M_base(); }
00722 
00723   template<typename _Tp, typename _Alloc>
00724     inline bool
00725     operator>=(const list<_Tp, _Alloc>& __lhs,
00726            const list<_Tp, _Alloc>& __rhs)
00727     { return __lhs._M_base() >= __rhs._M_base(); }
00728 
00729   template<typename _Tp, typename _Alloc>
00730     inline bool
00731     operator>(const list<_Tp, _Alloc>& __lhs,
00732           const list<_Tp, _Alloc>& __rhs)
00733     { return __lhs._M_base() > __rhs._M_base(); }
00734 
00735   template<typename _Tp, typename _Alloc>
00736     inline void
00737     swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
00738     { __lhs.swap(__rhs); }
00739 
00740 } // namespace __debug
00741 } // namespace std
00742 
00743 #endif