# debug/vector

Go to the documentation of this file.

    00001 // Debugging vector implementation -*- C++ -*-
    00002
    00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007
    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 2, 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 // You should have received a copy of the GNU General Public License along
    00018 // with this library; see the file COPYING.  If not, write to the Free
    00019 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    00020 // USA.
    00021
    00022 // As a special exception, you may use this file as part of a free software
    00023 // library without restriction.  Specifically, if other files instantiate
    00024 // templates or use macros or inline functions from this file, or you compile
    00025 // this file and link it with other files to produce an executable, this
    00026 // file does not by itself cause the resulting executable to be covered by
    00027 // the GNU General Public License.  This exception does not however
    00028 // invalidate any other reasons why the executable file might be covered by
    00029 // the GNU General Public License.
    00030
    00031 /** @file debug/vector
    00032  *  This file is a GNU debug extension to the Standard C++ Library.
    00033  */
    00034
    00035 #ifndef _GLIBCXX_DEBUG_VECTOR
    00036 #define _GLIBCXX_DEBUG_VECTOR 1
    00037
    00038 #include <vector>
    00039 #include <utility>
    00040 #include <debug/safe_sequence.h>
    00041 #include <debug/safe_iterator.h>
    00042
    00043 namespace std
    00044 {
    00045 namespace __debug
    00046 {
    00047   template<typename _Tp,
    00048        typename _Allocator = std::allocator<_Tp> >
    00049     class vector
    00050     : public _GLIBCXX_STD_D::vector<_Tp, _Allocator>,
    00051       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
    00052     {
    00053       typedef _GLIBCXX_STD_D::vector<_Tp, _Allocator> _Base;
    00054       typedef __gnu_debug::_Safe_sequence<vector>              _Safe_base;
    00055
    00056       typedef typename _Base::const_iterator _Base_const_iterator;
    00057       typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
    00058
    00059     public:
    00060       typedef typename _Base::reference             reference;
    00061       typedef typename _Base::const_reference       const_reference;
    00062
    00063       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,vector>
    00064       iterator;
    00065       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,vector>
    00066       const_iterator;
    00067
    00068       typedef typename _Base::size_type             size_type;
    00069       typedef typename _Base::difference_type       difference_type;
    00070
    00071       typedef _Tp                   value_type;
    00072       typedef _Allocator                allocator_type;
    00073       typedef typename _Base::pointer               pointer;
    00074       typedef typename _Base::const_pointer         const_pointer;
    00075       typedef std::reverse_iterator<iterator>       reverse_iterator;
    00076       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
    00077
    00078       // 23.2.4.1 construct/copy/destroy:
    00079       explicit vector(const _Allocator& __a = _Allocator())
    00080       : _Base(__a), _M_guaranteed_capacity(0) { }
    00081
    00082       explicit vector(size_type __n, const _Tp& __value = _Tp(),
    00083               const _Allocator& __a = _Allocator())
    00084       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
    00085
    00086       template<class _InputIterator>
    00087         vector(_InputIterator __first, _InputIterator __last,
    00088            const _Allocator& __a = _Allocator())
    00089     : _Base(__gnu_debug::__check_valid_range(__first, __last),
    00090         __last, __a),
    00091       _M_guaranteed_capacity(0)
    00092         { _M_update_guaranteed_capacity(); }
    00093
    00094       vector(const vector& __x)
    00095       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
    00096
    00097       /// Construction from a release-mode vector
    00098       vector(const _Base& __x)
    00099       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
    00100
    00101 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00102       vector(vector&& __x)
    00103       : _Base(std::forward<vector>(__x)), _Safe_base(),
    00104     _M_guaranteed_capacity(this->size())
    00105       {
    00106     this->_M_swap(__x);
    00107     __x._M_guaranteed_capacity = 0;
    00108       }
    00109 #endif
    00110
    00111       ~vector() { }
    00112
    00113       vector&
    00114       operator=(const vector& __x)
    00115       {
    00116     static_cast<_Base&>(*this) = __x;
    00117     this->_M_invalidate_all();
    00118     _M_update_guaranteed_capacity();
    00119     return *this;
    00120       }
    00121
    00122 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00123       vector&
    00124       operator=(vector&& __x)
    00125       {
    00126         // NB: DR 675.
    00127     clear();
    00128     swap(__x);
    00129     return *this;
    00130       }
    00131 #endif
    00132
    00133       template<typename _InputIterator>
    00134         void
    00135         assign(_InputIterator __first, _InputIterator __last)
    00136         {
    00137       __glibcxx_check_valid_range(__first, __last);
    00138       _Base::assign(__first, __last);
    00139       this->_M_invalidate_all();
    00140       _M_update_guaranteed_capacity();
    00141     }
    00142
    00143       void
    00144       assign(size_type __n, const _Tp& __u)
    00145       {
    00146     _Base::assign(__n, __u);
    00147     this->_M_invalidate_all();
    00148     _M_update_guaranteed_capacity();
    00149       }
    00150
    00151       using _Base::get_allocator;
    00152
    00153       // iterators:
    00154       iterator
    00155       begin()
    00156       { return iterator(_Base::begin(), this); }
    00157
    00158       const_iterator
    00159       begin() const
    00160       { return const_iterator(_Base::begin(), this); }
    00161
    00162       iterator
    00163       end()
    00164       { return iterator(_Base::end(), this); }
    00165
    00166       const_iterator
    00167       end() const
    00168       { return const_iterator(_Base::end(), this); }
    00169
    00170       reverse_iterator
    00171       rbegin()
    00172       { return reverse_iterator(end()); }
    00173
    00174       const_reverse_iterator
    00175       rbegin() const
    00176       { return const_reverse_iterator(end()); }
    00177
    00178       reverse_iterator
    00179       rend()
    00180       { return reverse_iterator(begin()); }
    00181
    00182       const_reverse_iterator
    00183       rend() const
    00184       { return const_reverse_iterator(begin()); }
    00185
    00186 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00187       const_iterator
    00188       cbegin() const
    00189       { return const_iterator(_Base::begin(), this); }
    00190
    00191       const_iterator
    00192       cend() const
    00193       { return const_iterator(_Base::end(), this); }
    00194
    00195       const_reverse_iterator
    00196       crbegin() const
    00197       { return const_reverse_iterator(end()); }
    00198
    00199       const_reverse_iterator
    00200       crend() const
    00201       { return const_reverse_iterator(begin()); }
    00202 #endif
    00203
    00204       // 23.2.4.2 capacity:
    00205       using _Base::size;
    00206       using _Base::max_size;
    00207
    00208       void
    00209       resize(size_type __sz, _Tp __c = _Tp())
    00210       {
    00211     bool __realloc = _M_requires_reallocation(__sz);
    00212     if (__sz < this->size())
    00213       this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
    00214     _Base::resize(__sz, __c);
    00215     if (__realloc)
    00216       this->_M_invalidate_all();
    00217       }
    00218
    00219       using _Base::capacity;
    00220       using _Base::empty;
    00221
    00222       void
    00223       reserve(size_type __n)
    00224       {
    00225     bool __realloc = _M_requires_reallocation(__n);
    00226     _Base::reserve(__n);
    00227     if (__n > _M_guaranteed_capacity)
    00228       _M_guaranteed_capacity = __n;
    00229     if (__realloc)
    00230       this->_M_invalidate_all();
    00231       }
    00232
    00233       // element access:
    00234       reference
    00235       operator[](size_type __n)
    00236       {
    00237     __glibcxx_check_subscript(__n);
    00238     return _M_base()[__n];
    00239       }
    00240
    00241       const_reference
    00242       operator[](size_type __n) const
    00243       {
    00244     __glibcxx_check_subscript(__n);
    00245     return _M_base()[__n];
    00246       }
    00247
    00248       using _Base::at;
    00249
    00250       reference
    00251       front()
    00252       {
    00253     __glibcxx_check_nonempty();
    00254     return _Base::front();
    00255       }
    00256
    00257       const_reference
    00258       front() const
    00259       {
    00260     __glibcxx_check_nonempty();
    00261     return _Base::front();
    00262       }
    00263
    00264       reference
    00265       back()
    00266       {
    00267     __glibcxx_check_nonempty();
    00268     return _Base::back();
    00269       }
    00270
    00271       const_reference
    00272       back() const
    00273       {
    00274     __glibcxx_check_nonempty();
    00275     return _Base::back();
    00276       }
    00277
    00278       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00279       // DR 464. Suggestion for new member functions in standard containers.
    00280       using _Base::data;
    00281
    00282       // 23.2.4.3 modifiers:
    00283 #ifndef __GXX_EXPERIMENTAL_CXX0X__
    00284       void
    00285       push_back(const _Tp& __x)
    00286       {
    00287     bool __realloc = _M_requires_reallocation(this->size() + 1);
    00288     _Base::push_back(__x);
    00289     if (__realloc)
    00290       this->_M_invalidate_all();
    00291     _M_update_guaranteed_capacity();
    00292       }
    00293 #else
    00294       template<typename... _Args>
    00295         void
    00296         push_back(_Args&&... __args)
    00297     {
    00298       bool __realloc = _M_requires_reallocation(this->size() + 1);
    00299       _Base::push_back(std::forward<_Args>(__args)...);
    00300       if (__realloc)
    00301         this->_M_invalidate_all();
    00302       _M_update_guaranteed_capacity();
    00303     }
    00304 #endif
    00305
    00306       void
    00307       pop_back()
    00308       {
    00309     __glibcxx_check_nonempty();
    00310     iterator __victim = end() - 1;
    00311     __victim._M_invalidate();
    00312     _Base::pop_back();
    00313       }
    00314
    00315 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00316       template<typename... _Args>
    00317         iterator
    00318         emplace(iterator __position, _Args&&... __args)
    00319     {
    00320       __glibcxx_check_insert(__position);
    00321       bool __realloc = _M_requires_reallocation(this->size() + 1);
    00322       difference_type __offset = __position - begin();
    00323       typename _Base::iterator __res = _Base::emplace(__position.base(),
    00324                         std::forward<_Args>(__args)...);
    00325       if (__realloc)
    00326         this->_M_invalidate_all();
    00327       else
    00328         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
    00329       _M_update_guaranteed_capacity();
    00330       return iterator(__res, this);
    00331     }
    00332 #endif
    00333
    00334       iterator
    00335       insert(iterator __position, const _Tp& __x)
    00336       {
    00337     __glibcxx_check_insert(__position);
    00338     bool __realloc = _M_requires_reallocation(this->size() + 1);
    00339     difference_type __offset = __position - begin();
    00340     typename _Base::iterator __res = _Base::insert(__position.base(),__x);
    00341     if (__realloc)
    00342       this->_M_invalidate_all();
    00343     else
    00344       this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
    00345     _M_update_guaranteed_capacity();
    00346     return iterator(__res, this);
    00347       }
    00348
    00349 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00350       iterator
    00351       insert(iterator __position, _Tp&& __x)
    00352       { return emplace(__position, std::move(__x)); }
    00353 #endif
    00354
    00355       void
    00356       insert(iterator __position, size_type __n, const _Tp& __x)
    00357       {
    00358     __glibcxx_check_insert(__position);
    00359     bool __realloc = _M_requires_reallocation(this->size() + __n);
    00360     difference_type __offset = __position - begin();
    00361     _Base::insert(__position.base(), __n, __x);
    00362     if (__realloc)
    00363       this->_M_invalidate_all();
    00364     else
    00365       this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
    00366     _M_update_guaranteed_capacity();
    00367       }
    00368
    00369       template<class _InputIterator>
    00370         void
    00371         insert(iterator __position,
    00372            _InputIterator __first, _InputIterator __last)
    00373         {
    00374       __glibcxx_check_insert_range(__position, __first, __last);
    00375
    00376       /* Hard to guess if invalidation will occur, because __last
    00377          - __first can't be calculated in all cases, so we just
    00378          punt here by checking if it did occur. */
    00379       typename _Base::iterator __old_begin = _M_base().begin();
    00380       difference_type __offset = __position - begin();
    00381       _Base::insert(__position.base(), __first, __last);
    00382
    00383       if (_M_base().begin() != __old_begin)
    00384         this->_M_invalidate_all();
    00385       else
    00386         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
    00387       _M_update_guaranteed_capacity();
    00388     }
    00389
    00390       iterator
    00391       erase(iterator __position)
    00392       {
    00393     __glibcxx_check_erase(__position);
    00394     difference_type __offset = __position - begin();
    00395     typename _Base::iterator __res = _Base::erase(__position.base());
    00396     this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
    00397     return iterator(__res, this);
    00398       }
    00399
    00400       iterator
    00401       erase(iterator __first, iterator __last)
    00402       {
    00403     // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00404     // 151. can't currently clear() empty container
    00405     __glibcxx_check_erase_range(__first, __last);
    00406
    00407     difference_type __offset = __first - begin();
    00408     typename _Base::iterator __res = _Base::erase(__first.base(),
    00409                              __last.base());
    00410     this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
    00411     return iterator(__res, this);
    00412       }
    00413
    00414       void
    00415 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00416       swap(vector&& __x)
    00417 #else
    00418       swap(vector& __x)
    00419 #endif
    00420       {
    00421     _Base::swap(__x);
    00422     this->_M_swap(__x);
    00423         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
    00424       }
    00425
    00426       void
    00427       clear()
    00428       {
    00429     _Base::clear();
    00430     this->_M_invalidate_all();
    00431         _M_guaranteed_capacity = 0;
    00432       }
    00433
    00434       _Base&
    00435       _M_base() { return *this; }
    00436
    00437       const _Base&
    00438       _M_base() const { return *this; }
    00439
    00440     private:
    00441       size_type _M_guaranteed_capacity;
    00442
    00443       bool
    00444       _M_requires_reallocation(size_type __elements)
    00445       {
    00446 #ifdef _GLIBCXX_DEBUG_PEDANTIC
    00447     return __elements > this->capacity();
    00448 #else
    00449     return __elements > _M_guaranteed_capacity;
    00450 #endif
    00451       }
    00452
    00453       void
    00454       _M_update_guaranteed_capacity()
    00455       {
    00456     if (this->size() > _M_guaranteed_capacity)
    00457       _M_guaranteed_capacity = this->size();
    00458       }
    00459     };
    00460
    00461   template<typename _Tp, typename _Alloc>
    00462     inline bool
    00463     operator==(const vector<_Tp, _Alloc>& __lhs,
    00464            const vector<_Tp, _Alloc>& __rhs)
    00465     { return __lhs._M_base() == __rhs._M_base(); }
    00466
    00467   template<typename _Tp, typename _Alloc>
    00468     inline bool
    00469     operator!=(const vector<_Tp, _Alloc>& __lhs,
    00470            const vector<_Tp, _Alloc>& __rhs)
    00471     { return __lhs._M_base() != __rhs._M_base(); }
    00472
    00473   template<typename _Tp, typename _Alloc>
    00474     inline bool
    00475     operator<(const vector<_Tp, _Alloc>& __lhs,
    00476           const vector<_Tp, _Alloc>& __rhs)
    00477     { return __lhs._M_base() < __rhs._M_base(); }
    00478
    00479   template<typename _Tp, typename _Alloc>
    00480     inline bool
    00481     operator<=(const vector<_Tp, _Alloc>& __lhs,
    00482            const vector<_Tp, _Alloc>& __rhs)
    00483     { return __lhs._M_base() <= __rhs._M_base(); }
    00484
    00485   template<typename _Tp, typename _Alloc>
    00486     inline bool
    00487     operator>=(const vector<_Tp, _Alloc>& __lhs,
    00488            const vector<_Tp, _Alloc>& __rhs)
    00489     { return __lhs._M_base() >= __rhs._M_base(); }
    00490
    00491   template<typename _Tp, typename _Alloc>
    00492     inline bool
    00493     operator>(const vector<_Tp, _Alloc>& __lhs,
    00494           const vector<_Tp, _Alloc>& __rhs)
    00495     { return __lhs._M_base() > __rhs._M_base(); }
    00496
    00497   template<typename _Tp, typename _Alloc>
    00498     inline void
    00499     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
    00500     { __lhs.swap(__rhs); }
    00501
    00502 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    00503   template<typename _Tp, typename _Alloc>
    00504     inline void
    00505     swap(vector<_Tp, _Alloc>&& __lhs, vector<_Tp, _Alloc>& __rhs)
    00506     { __lhs.swap(__rhs); }
    00507
    00508   template<typename _Tp, typename _Alloc>
    00509     inline void
    00510     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>&& __rhs)
    00511     { __lhs.swap(__rhs); }
    00512 #endif
    00513
    00514 } // namespace __debug
    00515 } // namespace std
    00516
    00517 #endif