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