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

Generated on 12 Mar 2010 for libstdc++ by  doxygen 1.6.1