debug/deque

Go to the documentation of this file.
00001 // Debugging deque 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/deque
00027  *  This file is a GNU debug extension to the Standard C++ Library.
00028  */
00029 
00030 #ifndef _GLIBCXX_DEBUG_DEQUE
00031 #define _GLIBCXX_DEBUG_DEQUE 1
00032 
00033 #include <deque>
00034 #include <debug/safe_sequence.h>
00035 #include <debug/safe_iterator.h>
00036 
00037 namespace std
00038 {
00039 namespace __debug
00040 {
00041   /// Class std::deque with safety/checking/debug instrumentation.
00042   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
00043     class deque
00044     : public _GLIBCXX_STD_D::deque<_Tp, _Allocator>,
00045       public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
00046     {
00047       typedef  _GLIBCXX_STD_D::deque<_Tp, _Allocator> _Base;
00048       typedef __gnu_debug::_Safe_sequence<deque> _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,deque>
00055                             iterator;
00056       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,deque>
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.1.1 construct/copy/destroy:
00070       explicit
00071       deque(const _Allocator& __a = _Allocator())
00072       : _Base(__a) { }
00073 
00074 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00075       explicit
00076       deque(size_type __n)
00077       : _Base(__n) { }
00078 
00079       deque(size_type __n, const _Tp& __value,
00080         const _Allocator& __a = _Allocator())
00081       : _Base(__n, __value, __a) { }
00082 #else
00083       explicit
00084       deque(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         deque(_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       deque(const deque& __x)
00098       : _Base(__x), _Safe_base() { }
00099 
00100       deque(const _Base& __x)
00101       : _Base(__x), _Safe_base() { }
00102 
00103 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00104       deque(deque&& __x)
00105       : _Base(std::move(__x)), _Safe_base()
00106       { this->_M_swap(__x); }
00107 
00108       deque(initializer_list<value_type> __l,
00109         const allocator_type& __a = allocator_type())
00110       : _Base(__l, __a), _Safe_base() { }
00111 #endif
00112 
00113       ~deque() { }
00114 
00115       deque&
00116       operator=(const deque& __x)
00117       {
00118     *static_cast<_Base*>(this) = __x;
00119     this->_M_invalidate_all();
00120     return *this;
00121       }
00122 
00123 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00124       deque&
00125       operator=(deque&& __x)
00126       {
00127     // NB: DR 1204.
00128     // NB: DR 675.
00129     clear();
00130     swap(__x);
00131     return *this;
00132       }
00133 
00134       deque&
00135       operator=(initializer_list<value_type> __l)
00136       {
00137     *static_cast<_Base*>(this) = __l;
00138     this->_M_invalidate_all();
00139     return *this;
00140       }
00141 #endif
00142 
00143       template<class _InputIterator>
00144         void
00145         assign(_InputIterator __first, _InputIterator __last)
00146         {
00147       __glibcxx_check_valid_range(__first, __last);
00148       _Base::assign(__gnu_debug::__base(__first),
00149             __gnu_debug::__base(__last));
00150       this->_M_invalidate_all();
00151     }
00152 
00153       void
00154       assign(size_type __n, const _Tp& __t)
00155       {
00156     _Base::assign(__n, __t);
00157     this->_M_invalidate_all();
00158       }
00159 
00160 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00161       void
00162       assign(initializer_list<value_type> __l)
00163       {
00164     _Base::assign(__l);
00165     this->_M_invalidate_all();
00166       }
00167 #endif
00168 
00169       using _Base::get_allocator;
00170 
00171       // iterators:
00172       iterator
00173       begin()
00174       { return iterator(_Base::begin(), this); }
00175 
00176       const_iterator
00177       begin() const
00178       { return const_iterator(_Base::begin(), this); }
00179 
00180       iterator
00181       end()
00182       { return iterator(_Base::end(), this); }
00183 
00184       const_iterator
00185       end() const
00186       { return const_iterator(_Base::end(), this); }
00187 
00188       reverse_iterator
00189       rbegin()
00190       { return reverse_iterator(end()); }
00191 
00192       const_reverse_iterator
00193       rbegin() const
00194       { return const_reverse_iterator(end()); }
00195 
00196       reverse_iterator
00197       rend()
00198       { return reverse_iterator(begin()); }
00199 
00200       const_reverse_iterator
00201       rend() const
00202       { return const_reverse_iterator(begin()); }
00203 
00204 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00205       const_iterator
00206       cbegin() const
00207       { return const_iterator(_Base::begin(), this); }
00208 
00209       const_iterator
00210       cend() const
00211       { return const_iterator(_Base::end(), this); }
00212 
00213       const_reverse_iterator
00214       crbegin() const
00215       { return const_reverse_iterator(end()); }
00216 
00217       const_reverse_iterator
00218       crend() const
00219       { return const_reverse_iterator(begin()); }
00220 #endif
00221 
00222       // 23.2.1.2 capacity:
00223       using _Base::size;
00224       using _Base::max_size;
00225 
00226 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00227       void
00228       resize(size_type __sz)
00229       {
00230     typedef typename _Base::const_iterator _Base_const_iterator;
00231     typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
00232 
00233     bool __invalidate_all = __sz > this->size();
00234     if (__sz < this->size())
00235       this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
00236 
00237     _Base::resize(__sz);
00238 
00239     if (__invalidate_all)
00240       this->_M_invalidate_all();
00241       }
00242 
00243       void
00244       resize(size_type __sz, const _Tp& __c)
00245       {
00246     typedef typename _Base::const_iterator _Base_const_iterator;
00247     typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
00248 
00249     bool __invalidate_all = __sz > this->size();
00250     if (__sz < this->size())
00251       this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
00252 
00253     _Base::resize(__sz, __c);
00254 
00255     if (__invalidate_all)
00256       this->_M_invalidate_all();
00257       }
00258 #else
00259       void
00260       resize(size_type __sz, _Tp __c = _Tp())
00261       {
00262     typedef typename _Base::const_iterator _Base_const_iterator;
00263     typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
00264 
00265     bool __invalidate_all = __sz > this->size();
00266     if (__sz < this->size())
00267       this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
00268 
00269     _Base::resize(__sz, __c);
00270 
00271     if (__invalidate_all)
00272       this->_M_invalidate_all();
00273       }
00274 #endif
00275 
00276 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00277       using _Base::shrink_to_fit;
00278 #endif
00279 
00280       using _Base::empty;
00281 
00282       // element access:
00283       reference
00284       operator[](size_type __n)
00285       {
00286     __glibcxx_check_subscript(__n);
00287     return _M_base()[__n];
00288       }
00289 
00290       const_reference
00291       operator[](size_type __n) const
00292       {
00293     __glibcxx_check_subscript(__n);
00294     return _M_base()[__n];
00295       }
00296 
00297       using _Base::at;
00298 
00299       reference
00300       front()
00301       {
00302     __glibcxx_check_nonempty();
00303     return _Base::front();
00304       }
00305 
00306       const_reference
00307       front() const
00308       {
00309     __glibcxx_check_nonempty();
00310     return _Base::front();
00311       }
00312 
00313       reference
00314       back()
00315       {
00316     __glibcxx_check_nonempty();
00317     return _Base::back();
00318       }
00319 
00320       const_reference
00321       back() const
00322       {
00323     __glibcxx_check_nonempty();
00324     return _Base::back();
00325       }
00326 
00327       // 23.2.1.3 modifiers:
00328       void
00329       push_front(const _Tp& __x)
00330       {
00331     _Base::push_front(__x);
00332     this->_M_invalidate_all();
00333       }
00334 
00335       void
00336       push_back(const _Tp& __x)
00337       {
00338     _Base::push_back(__x);
00339     this->_M_invalidate_all();
00340       }
00341 
00342 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00343       void
00344       push_front(_Tp&& __x)
00345       { emplace_front(std::move(__x)); }
00346 
00347       void
00348       push_back(_Tp&& __x)
00349       { emplace_back(std::move(__x)); }
00350 
00351       template<typename... _Args>
00352         void
00353         emplace_front(_Args&&... __args)
00354     {
00355       _Base::emplace_front(std::forward<_Args>(__args)...);
00356       this->_M_invalidate_all();
00357     }
00358 
00359       template<typename... _Args>
00360         void
00361         emplace_back(_Args&&... __args)
00362     {
00363       _Base::emplace_back(std::forward<_Args>(__args)...);
00364       this->_M_invalidate_all();
00365     }
00366 
00367       template<typename... _Args>
00368         iterator
00369         emplace(iterator __position, _Args&&... __args)
00370     {
00371       __glibcxx_check_insert(__position);
00372       typename _Base::iterator __res = _Base::emplace(__position.base(),
00373                         std::forward<_Args>(__args)...);
00374       this->_M_invalidate_all();
00375       return iterator(__res, this);
00376     }
00377 #endif
00378 
00379       iterator
00380       insert(iterator __position, const _Tp& __x)
00381       {
00382     __glibcxx_check_insert(__position);
00383     typename _Base::iterator __res = _Base::insert(__position.base(), __x);
00384     this->_M_invalidate_all();
00385     return iterator(__res, this);
00386       }
00387 
00388 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00389       iterator
00390       insert(iterator __position, _Tp&& __x)
00391       { return emplace(__position, std::move(__x)); }
00392 
00393       void
00394       insert(iterator __p, initializer_list<value_type> __l)
00395       {
00396     _Base::insert(__p, __l);
00397     this->_M_invalidate_all();
00398       }
00399 #endif
00400 
00401       void
00402       insert(iterator __position, size_type __n, const _Tp& __x)
00403       {
00404     __glibcxx_check_insert(__position);
00405     _Base::insert(__position.base(), __n, __x);
00406     this->_M_invalidate_all();
00407       }
00408 
00409       template<class _InputIterator>
00410         void
00411         insert(iterator __position,
00412            _InputIterator __first, _InputIterator __last)
00413         {
00414       __glibcxx_check_insert_range(__position, __first, __last);
00415       _Base::insert(__position.base(), __gnu_debug::__base(__first),
00416                        __gnu_debug::__base(__last));
00417       this->_M_invalidate_all();
00418     }
00419 
00420       void
00421       pop_front()
00422       {
00423     __glibcxx_check_nonempty();
00424     iterator __victim = begin();
00425     __victim._M_invalidate();
00426     _Base::pop_front();
00427       }
00428 
00429       void
00430       pop_back()
00431       {
00432     __glibcxx_check_nonempty();
00433     iterator __victim = end();
00434     --__victim;
00435     __victim._M_invalidate();
00436     _Base::pop_back();
00437       }
00438 
00439       iterator
00440       erase(iterator __position)
00441       {
00442     __glibcxx_check_erase(__position);
00443     if (__position == begin() || __position == end()-1)
00444       {
00445         __position._M_invalidate();
00446         return iterator(_Base::erase(__position.base()), this);
00447       }
00448     else
00449       {
00450         typename _Base::iterator __res = _Base::erase(__position.base());
00451         this->_M_invalidate_all();
00452         return iterator(__res, this);
00453       }
00454       }
00455 
00456       iterator
00457       erase(iterator __first, iterator __last)
00458       {
00459     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00460     // 151. can't currently clear() empty container
00461     __glibcxx_check_erase_range(__first, __last);
00462         if (__first == begin() || __last == end())
00463       {
00464         this->_M_detach_singular();
00465         for (iterator __position = __first; __position != __last; )
00466           {
00467         iterator __victim = __position++;
00468         __victim._M_invalidate();
00469           }
00470         __try
00471           {
00472         return iterator(_Base::erase(__first.base(), __last.base()),
00473                 this);
00474           }
00475         __catch(...)
00476           {
00477         this->_M_revalidate_singular();
00478         __throw_exception_again;
00479           }
00480       }
00481     else
00482       {
00483         typename _Base::iterator __res = _Base::erase(__first.base(),
00484                               __last.base());
00485         this->_M_invalidate_all();
00486         return iterator(__res, this);
00487       }
00488       }
00489 
00490       void
00491       swap(deque& __x)
00492       {
00493     _Base::swap(__x);
00494     this->_M_swap(__x);
00495       }
00496 
00497       void
00498       clear()
00499       {
00500     _Base::clear();
00501     this->_M_invalidate_all();
00502       }
00503 
00504       _Base&
00505       _M_base()       { return *this; }
00506 
00507       const _Base&
00508       _M_base() const { return *this; }
00509     };
00510 
00511   template<typename _Tp, typename _Alloc>
00512     inline bool
00513     operator==(const deque<_Tp, _Alloc>& __lhs,
00514            const deque<_Tp, _Alloc>& __rhs)
00515     { return __lhs._M_base() == __rhs._M_base(); }
00516 
00517   template<typename _Tp, typename _Alloc>
00518     inline bool
00519     operator!=(const deque<_Tp, _Alloc>& __lhs,
00520            const deque<_Tp, _Alloc>& __rhs)
00521     { return __lhs._M_base() != __rhs._M_base(); }
00522 
00523   template<typename _Tp, typename _Alloc>
00524     inline bool
00525     operator<(const deque<_Tp, _Alloc>& __lhs,
00526           const deque<_Tp, _Alloc>& __rhs)
00527     { return __lhs._M_base() < __rhs._M_base(); }
00528 
00529   template<typename _Tp, typename _Alloc>
00530     inline bool
00531     operator<=(const deque<_Tp, _Alloc>& __lhs,
00532            const deque<_Tp, _Alloc>& __rhs)
00533     { return __lhs._M_base() <= __rhs._M_base(); }
00534 
00535   template<typename _Tp, typename _Alloc>
00536     inline bool
00537     operator>=(const deque<_Tp, _Alloc>& __lhs,
00538            const deque<_Tp, _Alloc>& __rhs)
00539     { return __lhs._M_base() >= __rhs._M_base(); }
00540 
00541   template<typename _Tp, typename _Alloc>
00542     inline bool
00543     operator>(const deque<_Tp, _Alloc>& __lhs,
00544           const deque<_Tp, _Alloc>& __rhs)
00545     { return __lhs._M_base() > __rhs._M_base(); }
00546 
00547   template<typename _Tp, typename _Alloc>
00548     inline void
00549     swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs)
00550     { __lhs.swap(__rhs); }
00551 
00552 } // namespace __debug
00553 } // namespace std
00554 
00555 #endif