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