debug/vector

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

Generated on 11 Jan 2010 for libstdc++ by  doxygen 1.6.1