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 // 2012
00005 // Free Software Foundation, Inc.
00006 //
00007 // This file is part of the GNU ISO C++ Library.  This library is free
00008 // software; you can redistribute it and/or modify it under the
00009 // terms of the GNU General Public License as published by the
00010 // Free Software Foundation; either version 3, or (at your option)
00011 // any later version.
00012 
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 
00018 // Under Section 7 of GPL version 3, you are granted additional
00019 // permissions described in the GCC Runtime Library Exception, version
00020 // 3.1, as published by the Free Software Foundation.
00021 
00022 // You should have received a copy of the GNU General Public License and
00023 // a copy of the GCC Runtime Library Exception along with this program;
00024 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00025 // <http://www.gnu.org/licenses/>.
00026 
00027 /** @file debug/deque
00028  *  This file is a GNU debug extension to the Standard C++ Library.
00029  */
00030 
00031 #ifndef _GLIBCXX_DEBUG_DEQUE
00032 #define _GLIBCXX_DEBUG_DEQUE 1
00033 
00034 #include <deque>
00035 #include <debug/safe_sequence.h>
00036 #include <debug/safe_iterator.h>
00037 
00038 namespace std _GLIBCXX_VISIBILITY(default)
00039 {
00040 namespace __debug
00041 {
00042   /// Class std::deque with safety/checking/debug instrumentation.
00043   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
00044     class deque
00045     : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>,
00046       public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
00047     {
00048       typedef  _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base;
00049 
00050       typedef typename _Base::const_iterator _Base_const_iterator;
00051       typedef typename _Base::iterator _Base_iterator;
00052       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
00053     public:
00054       typedef typename _Base::reference             reference;
00055       typedef typename _Base::const_reference       const_reference;
00056 
00057       typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque>
00058                             iterator;
00059       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque>
00060                             const_iterator;
00061 
00062       typedef typename _Base::size_type             size_type;
00063       typedef typename _Base::difference_type       difference_type;
00064 
00065       typedef _Tp                   value_type;
00066       typedef _Allocator                allocator_type;
00067       typedef typename _Base::pointer               pointer;
00068       typedef typename _Base::const_pointer         const_pointer;
00069       typedef std::reverse_iterator<iterator>       reverse_iterator;
00070       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00071 
00072       // 23.2.1.1 construct/copy/destroy:
00073       explicit
00074       deque(const _Allocator& __a = _Allocator())
00075       : _Base(__a) { }
00076 
00077 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00078       explicit
00079       deque(size_type __n)
00080       : _Base(__n) { }
00081 
00082       deque(size_type __n, const _Tp& __value,
00083         const _Allocator& __a = _Allocator())
00084       : _Base(__n, __value, __a) { }
00085 #else
00086       explicit
00087       deque(size_type __n, const _Tp& __value = _Tp(),
00088         const _Allocator& __a = _Allocator())
00089       : _Base(__n, __value, __a) { }
00090 #endif
00091 
00092 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00093       template<class _InputIterator,
00094            typename = std::_RequireInputIter<_InputIterator>>
00095 #else
00096       template<class _InputIterator>
00097 #endif
00098         deque(_InputIterator __first, _InputIterator __last,
00099           const _Allocator& __a = _Allocator())
00100     : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
00101                                      __last)),
00102         __gnu_debug::__base(__last), __a)
00103         { }
00104 
00105       deque(const deque& __x)
00106       : _Base(__x) { }
00107 
00108       deque(const _Base& __x)
00109       : _Base(__x) { }
00110 
00111 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00112       deque(deque&& __x)
00113       : _Base(std::move(__x))
00114       { this->_M_swap(__x); }
00115 
00116       deque(initializer_list<value_type> __l,
00117         const allocator_type& __a = allocator_type())
00118       : _Base(__l, __a) { }
00119 #endif
00120 
00121       ~deque() _GLIBCXX_NOEXCEPT { }
00122 
00123       deque&
00124       operator=(const deque& __x)
00125       {
00126     *static_cast<_Base*>(this) = __x;
00127     this->_M_invalidate_all();
00128     return *this;
00129       }
00130 
00131 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00132       deque&
00133       operator=(deque&& __x)
00134       {
00135     // NB: DR 1204.
00136     // NB: DR 675.
00137     __glibcxx_check_self_move_assign(__x);
00138     clear();
00139     swap(__x);
00140     return *this;
00141       }
00142 
00143       deque&
00144       operator=(initializer_list<value_type> __l)
00145       {
00146     *static_cast<_Base*>(this) = __l;
00147     this->_M_invalidate_all();
00148     return *this;
00149       }
00150 #endif
00151 
00152 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00153       template<class _InputIterator,
00154            typename = std::_RequireInputIter<_InputIterator>>
00155 #else
00156       template<class _InputIterator>
00157 #endif
00158         void
00159         assign(_InputIterator __first, _InputIterator __last)
00160         {
00161       __glibcxx_check_valid_range(__first, __last);
00162       _Base::assign(__gnu_debug::__base(__first),
00163             __gnu_debug::__base(__last));
00164       this->_M_invalidate_all();
00165     }
00166 
00167       void
00168       assign(size_type __n, const _Tp& __t)
00169       {
00170     _Base::assign(__n, __t);
00171     this->_M_invalidate_all();
00172       }
00173 
00174 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00175       void
00176       assign(initializer_list<value_type> __l)
00177       {
00178     _Base::assign(__l);
00179     this->_M_invalidate_all();
00180       }
00181 #endif
00182 
00183       using _Base::get_allocator;
00184 
00185       // iterators:
00186       iterator
00187       begin() _GLIBCXX_NOEXCEPT
00188       { return iterator(_Base::begin(), this); }
00189 
00190       const_iterator
00191       begin() const _GLIBCXX_NOEXCEPT
00192       { return const_iterator(_Base::begin(), this); }
00193 
00194       iterator
00195       end() _GLIBCXX_NOEXCEPT
00196       { return iterator(_Base::end(), this); }
00197 
00198       const_iterator
00199       end() const _GLIBCXX_NOEXCEPT
00200       { return const_iterator(_Base::end(), this); }
00201 
00202       reverse_iterator
00203       rbegin() _GLIBCXX_NOEXCEPT
00204       { return reverse_iterator(end()); }
00205 
00206       const_reverse_iterator
00207       rbegin() const _GLIBCXX_NOEXCEPT
00208       { return const_reverse_iterator(end()); }
00209 
00210       reverse_iterator
00211       rend() _GLIBCXX_NOEXCEPT
00212       { return reverse_iterator(begin()); }
00213 
00214       const_reverse_iterator
00215       rend() const _GLIBCXX_NOEXCEPT
00216       { return const_reverse_iterator(begin()); }
00217 
00218 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00219       const_iterator
00220       cbegin() const noexcept
00221       { return const_iterator(_Base::begin(), this); }
00222 
00223       const_iterator
00224       cend() const noexcept
00225       { return const_iterator(_Base::end(), this); }
00226 
00227       const_reverse_iterator
00228       crbegin() const noexcept
00229       { return const_reverse_iterator(end()); }
00230 
00231       const_reverse_iterator
00232       crend() const noexcept
00233       { return const_reverse_iterator(begin()); }
00234 #endif
00235 
00236     private:
00237       void
00238       _M_invalidate_after_nth(difference_type __n)
00239       {
00240     typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
00241     this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
00242       }
00243       
00244     public:
00245       // 23.2.1.2 capacity:
00246       using _Base::size;
00247       using _Base::max_size;
00248 
00249 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00250       void
00251       resize(size_type __sz)
00252       {
00253     bool __invalidate_all = __sz > this->size();
00254     if (__sz < this->size())
00255       this->_M_invalidate_after_nth(__sz);
00256 
00257     _Base::resize(__sz);
00258 
00259     if (__invalidate_all)
00260       this->_M_invalidate_all();
00261       }
00262 
00263       void
00264       resize(size_type __sz, const _Tp& __c)
00265       {
00266     bool __invalidate_all = __sz > this->size();
00267     if (__sz < this->size())
00268       this->_M_invalidate_after_nth(__sz);
00269 
00270     _Base::resize(__sz, __c);
00271 
00272     if (__invalidate_all)
00273       this->_M_invalidate_all();
00274       }
00275 #else
00276       void
00277       resize(size_type __sz, _Tp __c = _Tp())
00278       {
00279     bool __invalidate_all = __sz > this->size();
00280     if (__sz < this->size())
00281       this->_M_invalidate_after_nth(__sz);
00282 
00283     _Base::resize(__sz, __c);
00284 
00285     if (__invalidate_all)
00286       this->_M_invalidate_all();
00287       }
00288 #endif
00289 
00290 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00291       void
00292       shrink_to_fit()
00293       {
00294     if (_Base::_M_shrink_to_fit())
00295       this->_M_invalidate_all();
00296       }
00297 #endif
00298 
00299       using _Base::empty;
00300 
00301       // element access:
00302       reference
00303       operator[](size_type __n)
00304       {
00305     __glibcxx_check_subscript(__n);
00306     return _M_base()[__n];
00307       }
00308 
00309       const_reference
00310       operator[](size_type __n) const
00311       {
00312     __glibcxx_check_subscript(__n);
00313     return _M_base()[__n];
00314       }
00315 
00316       using _Base::at;
00317 
00318       reference
00319       front()
00320       {
00321     __glibcxx_check_nonempty();
00322     return _Base::front();
00323       }
00324 
00325       const_reference
00326       front() const
00327       {
00328     __glibcxx_check_nonempty();
00329     return _Base::front();
00330       }
00331 
00332       reference
00333       back()
00334       {
00335     __glibcxx_check_nonempty();
00336     return _Base::back();
00337       }
00338 
00339       const_reference
00340       back() const
00341       {
00342     __glibcxx_check_nonempty();
00343     return _Base::back();
00344       }
00345 
00346       // 23.2.1.3 modifiers:
00347       void
00348       push_front(const _Tp& __x)
00349       {
00350     _Base::push_front(__x);
00351     this->_M_invalidate_all();
00352       }
00353 
00354       void
00355       push_back(const _Tp& __x)
00356       {
00357     _Base::push_back(__x);
00358     this->_M_invalidate_all();
00359       }
00360 
00361 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00362       void
00363       push_front(_Tp&& __x)
00364       { emplace_front(std::move(__x)); }
00365 
00366       void
00367       push_back(_Tp&& __x)
00368       { emplace_back(std::move(__x)); }
00369 
00370       template<typename... _Args>
00371         void
00372         emplace_front(_Args&&... __args)
00373     {
00374       _Base::emplace_front(std::forward<_Args>(__args)...);
00375       this->_M_invalidate_all();
00376     }
00377 
00378       template<typename... _Args>
00379         void
00380         emplace_back(_Args&&... __args)
00381     {
00382       _Base::emplace_back(std::forward<_Args>(__args)...);
00383       this->_M_invalidate_all();
00384     }
00385 
00386       template<typename... _Args>
00387         iterator
00388         emplace(iterator __position, _Args&&... __args)
00389     {
00390       __glibcxx_check_insert(__position);
00391       _Base_iterator __res = _Base::emplace(__position.base(),
00392                         std::forward<_Args>(__args)...);
00393       this->_M_invalidate_all();
00394       return iterator(__res, this);
00395     }
00396 #endif
00397 
00398       iterator
00399       insert(iterator __position, const _Tp& __x)
00400       {
00401     __glibcxx_check_insert(__position);
00402     _Base_iterator __res = _Base::insert(__position.base(), __x);
00403     this->_M_invalidate_all();
00404     return iterator(__res, this);
00405       }
00406 
00407 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00408       iterator
00409       insert(iterator __position, _Tp&& __x)
00410       { return emplace(__position, std::move(__x)); }
00411 
00412       void
00413       insert(iterator __p, initializer_list<value_type> __l)
00414       {
00415     _Base::insert(__p, __l);
00416     this->_M_invalidate_all();
00417       }
00418 #endif
00419 
00420       void
00421       insert(iterator __position, size_type __n, const _Tp& __x)
00422       {
00423     __glibcxx_check_insert(__position);
00424     _Base::insert(__position.base(), __n, __x);
00425     this->_M_invalidate_all();
00426       }
00427 
00428 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00429       template<class _InputIterator,
00430            typename = std::_RequireInputIter<_InputIterator>>
00431 #else
00432       template<class _InputIterator>
00433 #endif
00434         void
00435         insert(iterator __position,
00436            _InputIterator __first, _InputIterator __last)
00437         {
00438       __glibcxx_check_insert_range(__position, __first, __last);
00439       _Base::insert(__position.base(), __gnu_debug::__base(__first),
00440                        __gnu_debug::__base(__last));
00441       this->_M_invalidate_all();
00442     }
00443 
00444       void
00445       pop_front()
00446       {
00447     __glibcxx_check_nonempty();
00448     this->_M_invalidate_if(_Equal(_Base::begin()));
00449     _Base::pop_front();
00450       }
00451 
00452       void
00453       pop_back()
00454       {
00455     __glibcxx_check_nonempty();
00456     this->_M_invalidate_if(_Equal(--_Base::end()));
00457     _Base::pop_back();
00458       }
00459 
00460       iterator
00461       erase(iterator __position)
00462       {
00463     __glibcxx_check_erase(__position);
00464     _Base_iterator __victim = __position.base();
00465     if (__victim == _Base::begin() || __victim == _Base::end()-1)
00466       {
00467         this->_M_invalidate_if(_Equal(__victim));
00468         return iterator(_Base::erase(__victim), this);
00469       }
00470     else
00471       {
00472         _Base_iterator __res = _Base::erase(__victim);
00473         this->_M_invalidate_all();
00474         return iterator(__res, this);
00475       }
00476       }
00477 
00478       iterator
00479       erase(iterator __first, iterator __last)
00480       {
00481     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00482     // 151. can't currently clear() empty container
00483     __glibcxx_check_erase_range(__first, __last);
00484 
00485     if (__first.base() == __last.base())
00486       return __first;
00487         else if (__first.base() == _Base::begin()
00488          || __last.base() == _Base::end())
00489       {
00490         this->_M_detach_singular();
00491         for (_Base_iterator __position = __first.base();
00492          __position != __last.base(); ++__position)
00493           {
00494         this->_M_invalidate_if(_Equal(__position));
00495           }
00496         __try
00497           {
00498         return iterator(_Base::erase(__first.base(), __last.base()),
00499                 this);
00500           }
00501         __catch(...)
00502           {
00503         this->_M_revalidate_singular();
00504         __throw_exception_again;
00505           }
00506       }
00507     else
00508       {
00509         _Base_iterator __res = _Base::erase(__first.base(),
00510                         __last.base());
00511         this->_M_invalidate_all();
00512         return iterator(__res, this);
00513       }
00514       }
00515 
00516       void
00517       swap(deque& __x)
00518       {
00519     _Base::swap(__x);
00520     this->_M_swap(__x);
00521       }
00522 
00523       void
00524       clear() _GLIBCXX_NOEXCEPT
00525       {
00526     _Base::clear();
00527     this->_M_invalidate_all();
00528       }
00529 
00530       _Base&
00531       _M_base() _GLIBCXX_NOEXCEPT       { return *this; }
00532 
00533       const _Base&
00534       _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
00535     };
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 bool
00545     operator!=(const deque<_Tp, _Alloc>& __lhs,
00546            const deque<_Tp, _Alloc>& __rhs)
00547     { return __lhs._M_base() != __rhs._M_base(); }
00548 
00549   template<typename _Tp, typename _Alloc>
00550     inline bool
00551     operator<(const deque<_Tp, _Alloc>& __lhs,
00552           const deque<_Tp, _Alloc>& __rhs)
00553     { return __lhs._M_base() < __rhs._M_base(); }
00554 
00555   template<typename _Tp, typename _Alloc>
00556     inline bool
00557     operator<=(const deque<_Tp, _Alloc>& __lhs,
00558            const deque<_Tp, _Alloc>& __rhs)
00559     { return __lhs._M_base() <= __rhs._M_base(); }
00560 
00561   template<typename _Tp, typename _Alloc>
00562     inline bool
00563     operator>=(const deque<_Tp, _Alloc>& __lhs,
00564            const deque<_Tp, _Alloc>& __rhs)
00565     { return __lhs._M_base() >= __rhs._M_base(); }
00566 
00567   template<typename _Tp, typename _Alloc>
00568     inline bool
00569     operator>(const deque<_Tp, _Alloc>& __lhs,
00570           const deque<_Tp, _Alloc>& __rhs)
00571     { return __lhs._M_base() > __rhs._M_base(); }
00572 
00573   template<typename _Tp, typename _Alloc>
00574     inline void
00575     swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs)
00576     { __lhs.swap(__rhs); }
00577 
00578 } // namespace __debug
00579 } // namespace std
00580 
00581 #endif