vector

Go to the documentation of this file.
00001 // Debugging vector implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004, 2005
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 #ifndef _GLIBCXX_DEBUG_VECTOR
00032 #define _GLIBCXX_DEBUG_VECTOR 1
00033 
00034 #include <vector>
00035 #include <utility>
00036 #include <debug/safe_sequence.h>
00037 #include <debug/safe_iterator.h>
00038 
00039 namespace __gnu_debug_def
00040 {
00041   template<typename _Tp,
00042        typename _Allocator = std::allocator<_Tp> >
00043     class vector
00044     : public _GLIBCXX_STD::vector<_Tp, _Allocator>,
00045       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
00046     {
00047       typedef _GLIBCXX_STD::vector<_Tp, _Allocator> _Base;
00048       typedef __gnu_debug::_Safe_sequence<vector>              _Safe_base;
00049 
00050       typedef typename _Base::const_iterator _Base_const_iterator;
00051       typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
00052 
00053     public:
00054       typedef typename _Base::reference             reference;
00055       typedef typename _Base::const_reference       const_reference;
00056 
00057       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,vector>
00058       iterator;
00059       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,vector>
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.4.1 construct/copy/destroy:
00073       explicit vector(const _Allocator& __a = _Allocator())
00074       : _Base(__a), _M_guaranteed_capacity(0) { }
00075 
00076       explicit vector(size_type __n, const _Tp& __value = _Tp(),
00077               const _Allocator& __a = _Allocator())
00078       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
00079 
00080       template<class _InputIterator>
00081         vector(_InputIterator __first, _InputIterator __last,
00082            const _Allocator& __a = _Allocator())
00083     : _Base(__gnu_debug::__check_valid_range(__first, __last),
00084         __last, __a),
00085       _M_guaranteed_capacity(0)
00086         { _M_update_guaranteed_capacity(); }
00087 
00088       vector(const vector<_Tp,_Allocator>& __x)
00089       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
00090 
00092       vector(const _Base& __x)
00093       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
00094 
00095       ~vector() { }
00096 
00097       vector<_Tp,_Allocator>&
00098       operator=(const vector<_Tp,_Allocator>& __x)
00099       {
00100     static_cast<_Base&>(*this) = __x;
00101     this->_M_invalidate_all();
00102     _M_update_guaranteed_capacity();
00103     return *this;
00104       }
00105 
00106       template<typename _InputIterator>
00107         void
00108         assign(_InputIterator __first, _InputIterator __last)
00109         {
00110       __glibcxx_check_valid_range(__first, __last);
00111       _Base::assign(__first, __last);
00112       this->_M_invalidate_all();
00113       _M_update_guaranteed_capacity();
00114     }
00115 
00116       void
00117       assign(size_type __n, const _Tp& __u)
00118       {
00119     _Base::assign(__n, __u);
00120     this->_M_invalidate_all();
00121     _M_update_guaranteed_capacity();
00122       }
00123 
00124       using _Base::get_allocator;
00125 
00126       // iterators:
00127       iterator
00128       begin()
00129       { return iterator(_Base::begin(), this); }
00130 
00131       const_iterator
00132       begin() const
00133       { return const_iterator(_Base::begin(), this); }
00134 
00135       iterator
00136       end()
00137       { return iterator(_Base::end(), this); }
00138 
00139       const_iterator
00140       end() const
00141       { return const_iterator(_Base::end(), this); }
00142 
00143       reverse_iterator
00144       rbegin()
00145       { return reverse_iterator(end()); }
00146 
00147       const_reverse_iterator
00148       rbegin() const
00149       { return const_reverse_iterator(end()); }
00150 
00151       reverse_iterator
00152       rend()
00153       { return reverse_iterator(begin()); }
00154 
00155       const_reverse_iterator
00156       rend() const
00157       { return const_reverse_iterator(begin()); }
00158 
00159       // 23.2.4.2 capacity:
00160       using _Base::size;
00161       using _Base::max_size;
00162 
00163       void
00164       resize(size_type __sz, _Tp __c = _Tp())
00165       {
00166     bool __realloc = _M_requires_reallocation(__sz);
00167     if (__sz < this->size())
00168       this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
00169     _Base::resize(__sz, __c);
00170     if (__realloc)
00171       this->_M_invalidate_all();
00172       }
00173 
00174       using _Base::capacity;
00175       using _Base::empty;
00176 
00177       void
00178       reserve(size_type __n)
00179       {
00180     bool __realloc = _M_requires_reallocation(__n);
00181     _Base::reserve(__n);
00182     if (__n > _M_guaranteed_capacity)
00183       _M_guaranteed_capacity = __n;
00184     if (__realloc)
00185       this->_M_invalidate_all();
00186       }
00187 
00188       // element access:
00189       reference
00190       operator[](size_type __n)
00191       {
00192     __glibcxx_check_subscript(__n);
00193     return _M_base()[__n];
00194       }
00195 
00196       const_reference
00197       operator[](size_type __n) const
00198       {
00199     __glibcxx_check_subscript(__n);
00200     return _M_base()[__n];
00201       }
00202 
00203       using _Base::at;
00204 
00205       reference
00206       front()
00207       {
00208     __glibcxx_check_nonempty();
00209     return _Base::front();
00210       }
00211 
00212       const_reference
00213       front() const
00214       {
00215     __glibcxx_check_nonempty();
00216     return _Base::front();
00217       }
00218 
00219       reference
00220       back()
00221       {
00222     __glibcxx_check_nonempty();
00223     return _Base::back();
00224       }
00225 
00226       const_reference
00227       back() const
00228       {
00229     __glibcxx_check_nonempty();
00230     return _Base::back();
00231       }
00232 
00233       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00234       // DR 464. Suggestion for new member functions in standard containers.
00235       using _Base::data;
00236 
00237       // 23.2.4.3 modifiers:
00238       void
00239       push_back(const _Tp& __x)
00240       {
00241     bool __realloc = _M_requires_reallocation(this->size() + 1);
00242     _Base::push_back(__x);
00243     if (__realloc)
00244       this->_M_invalidate_all();
00245     _M_update_guaranteed_capacity();
00246       }
00247 
00248       void
00249       pop_back()
00250       {
00251     __glibcxx_check_nonempty();
00252     iterator __victim = end() - 1;
00253     __victim._M_invalidate();
00254     _Base::pop_back();
00255       }
00256 
00257       iterator
00258       insert(iterator __position, const _Tp& __x)
00259       {
00260     __glibcxx_check_insert(__position);
00261     bool __realloc = _M_requires_reallocation(this->size() + 1);
00262     difference_type __offset = __position - begin();
00263     typename _Base::iterator __res = _Base::insert(__position.base(),__x);
00264     if (__realloc)
00265       this->_M_invalidate_all();
00266     else
00267       this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
00268     _M_update_guaranteed_capacity();
00269     return iterator(__res, this);
00270       }
00271 
00272       void
00273       insert(iterator __position, size_type __n, const _Tp& __x)
00274       {
00275     __glibcxx_check_insert(__position);
00276     bool __realloc = _M_requires_reallocation(this->size() + __n);
00277     difference_type __offset = __position - begin();
00278     _Base::insert(__position.base(), __n, __x);
00279     if (__realloc)
00280       this->_M_invalidate_all();
00281     else
00282       this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
00283     _M_update_guaranteed_capacity();
00284       }
00285 
00286       template<class _InputIterator>
00287         void
00288         insert(iterator __position,
00289            _InputIterator __first, _InputIterator __last)
00290         {
00291       __glibcxx_check_insert_range(__position, __first, __last);
00292 
00293       /* Hard to guess if invalidation will occur, because __last
00294          - __first can't be calculated in all cases, so we just
00295          punt here by checking if it did occur. */
00296       typename _Base::iterator __old_begin = _M_base().begin();
00297       difference_type __offset = __position - begin();
00298       _Base::insert(__position.base(), __first, __last);
00299 
00300       if (_M_base().begin() != __old_begin)
00301         this->_M_invalidate_all();
00302       else
00303         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
00304       _M_update_guaranteed_capacity();
00305     }
00306 
00307       iterator
00308       erase(iterator __position)
00309       {
00310     __glibcxx_check_erase(__position);
00311     difference_type __offset = __position - begin();
00312     typename _Base::iterator __res = _Base::erase(__position.base());
00313     this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
00314     return iterator(__res, this);
00315       }
00316 
00317       iterator
00318       erase(iterator __first, iterator __last)
00319       {
00320     // _GLIBCXX_RESOLVE_LIB_DEFECTS
00321     // 151. can't currently clear() empty container
00322     __glibcxx_check_erase_range(__first, __last);
00323 
00324     difference_type __offset = __first - begin();
00325     typename _Base::iterator __res = _Base::erase(__first.base(),
00326                              __last.base());
00327     this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
00328     return iterator(__res, this);
00329       }
00330 
00331       void
00332       swap(vector<_Tp,_Allocator>& __x)
00333       {
00334     _Base::swap(__x);
00335     this->_M_swap(__x);
00336         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
00337       }
00338 
00339       void
00340       clear()
00341       {
00342     _Base::clear();
00343     this->_M_invalidate_all();
00344         _M_guaranteed_capacity = 0;
00345       }
00346 
00347       _Base&
00348       _M_base() { return *this; }
00349 
00350       const _Base&
00351       _M_base() const { return *this; }
00352 
00353     private:
00354       size_type _M_guaranteed_capacity;
00355 
00356       bool
00357       _M_requires_reallocation(size_type __elements)
00358       {
00359 #ifdef _GLIBCXX_DEBUG_PEDANTIC
00360     return __elements > this->capacity();
00361 #else
00362     return __elements > _M_guaranteed_capacity;
00363 #endif
00364       }
00365 
00366       void
00367       _M_update_guaranteed_capacity()
00368       {
00369     if (this->size() > _M_guaranteed_capacity)
00370       _M_guaranteed_capacity = this->size();
00371       }
00372     };
00373 
00374   template<typename _Tp, typename _Alloc>
00375     inline bool
00376     operator==(const vector<_Tp, _Alloc>& __lhs,
00377            const vector<_Tp, _Alloc>& __rhs)
00378     { return __lhs._M_base() == __rhs._M_base(); }
00379 
00380   template<typename _Tp, typename _Alloc>
00381     inline bool
00382     operator!=(const vector<_Tp, _Alloc>& __lhs,
00383            const vector<_Tp, _Alloc>& __rhs)
00384     { return __lhs._M_base() != __rhs._M_base(); }
00385 
00386   template<typename _Tp, typename _Alloc>
00387     inline bool
00388     operator<(const vector<_Tp, _Alloc>& __lhs,
00389           const vector<_Tp, _Alloc>& __rhs)
00390     { return __lhs._M_base() < __rhs._M_base(); }
00391 
00392   template<typename _Tp, typename _Alloc>
00393     inline bool
00394     operator<=(const vector<_Tp, _Alloc>& __lhs,
00395            const vector<_Tp, _Alloc>& __rhs)
00396     { return __lhs._M_base() <= __rhs._M_base(); }
00397 
00398   template<typename _Tp, typename _Alloc>
00399     inline bool
00400     operator>=(const vector<_Tp, _Alloc>& __lhs,
00401            const vector<_Tp, _Alloc>& __rhs)
00402     { return __lhs._M_base() >= __rhs._M_base(); }
00403 
00404   template<typename _Tp, typename _Alloc>
00405     inline bool
00406     operator>(const vector<_Tp, _Alloc>& __lhs,
00407           const vector<_Tp, _Alloc>& __rhs)
00408     { return __lhs._M_base() > __rhs._M_base(); }
00409 
00410   template<typename _Tp, typename _Alloc>
00411     inline void
00412     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
00413     { __lhs.swap(__rhs); }
00414 } // namespace __gnu_debug_def
00415 
00416 #endif

Generated on Tue Feb 2 16:57:01 2010 for GNU C++ STL by  doxygen 1.4.7