2005-12-18 Benjamin Kosnik <bkoz@redhat.com>
[official-gcc.git] / libstdc++-v3 / include / debug / vector
blob5a1fc92348b392724827c2dd0fd65494e11b03e7
1 // Debugging vector implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 // USA.
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
31 #ifndef _GLIBCXX_DEBUG_VECTOR
32 #define _GLIBCXX_DEBUG_VECTOR 1
34 #include <vector>
35 #include <utility>
36 #include <debug/safe_sequence.h>
37 #include <debug/safe_iterator.h>
39 namespace std
41 namespace __gnu_debug_def
43   template<typename _Tp,
44            typename _Allocator = std::allocator<_Tp> >
45     class vector
46     : public _GLIBCXX_STD::vector<_Tp, _Allocator>,
47       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
48     {
49       typedef _GLIBCXX_STD::vector<_Tp, _Allocator> _Base;
50       typedef __gnu_debug::_Safe_sequence<vector>              _Safe_base;
52       typedef typename _Base::const_iterator _Base_const_iterator;
53       typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
55     public:
56       typedef typename _Base::reference             reference;
57       typedef typename _Base::const_reference       const_reference;
59       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,vector>
60       iterator;
61       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,vector>
62       const_iterator;
64       typedef typename _Base::size_type             size_type;
65       typedef typename _Base::difference_type       difference_type;
67       typedef _Tp                                   value_type;
68       typedef _Allocator                            allocator_type;
69       typedef typename _Base::pointer               pointer;
70       typedef typename _Base::const_pointer         const_pointer;
71       typedef std::reverse_iterator<iterator>       reverse_iterator;
72       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
74       // 23.2.4.1 construct/copy/destroy:
75       explicit vector(const _Allocator& __a = _Allocator())
76       : _Base(__a), _M_guaranteed_capacity(0) { }
78       explicit vector(size_type __n, const _Tp& __value = _Tp(),
79                       const _Allocator& __a = _Allocator())
80       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
82       template<class _InputIterator>
83         vector(_InputIterator __first, _InputIterator __last,
84                const _Allocator& __a = _Allocator())
85         : _Base(__gnu_debug::__check_valid_range(__first, __last),
86                 __last, __a),
87           _M_guaranteed_capacity(0)
88         { _M_update_guaranteed_capacity(); }
90       vector(const vector<_Tp,_Allocator>& __x)
91       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
93       /// Construction from a release-mode vector
94       vector(const _Base& __x)
95       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
97       ~vector() { }
99       vector<_Tp,_Allocator>&
100       operator=(const vector<_Tp,_Allocator>& __x)
101       {
102         static_cast<_Base&>(*this) = __x;
103         this->_M_invalidate_all();
104         _M_update_guaranteed_capacity();
105         return *this;
106       }
108       template<typename _InputIterator>
109         void
110         assign(_InputIterator __first, _InputIterator __last)
111         {
112           __glibcxx_check_valid_range(__first, __last);
113           _Base::assign(__first, __last);
114           this->_M_invalidate_all();
115           _M_update_guaranteed_capacity();
116         }
118       void
119       assign(size_type __n, const _Tp& __u)
120       {
121         _Base::assign(__n, __u);
122         this->_M_invalidate_all();
123         _M_update_guaranteed_capacity();
124       }
126       using _Base::get_allocator;
128       // iterators:
129       iterator
130       begin()
131       { return iterator(_Base::begin(), this); }
133       const_iterator
134       begin() const
135       { return const_iterator(_Base::begin(), this); }
137       iterator
138       end()
139       { return iterator(_Base::end(), this); }
141       const_iterator
142       end() const
143       { return const_iterator(_Base::end(), this); }
145       reverse_iterator
146       rbegin()
147       { return reverse_iterator(end()); }
149       const_reverse_iterator
150       rbegin() const
151       { return const_reverse_iterator(end()); }
153       reverse_iterator
154       rend()
155       { return reverse_iterator(begin()); }
157       const_reverse_iterator
158       rend() const
159       { return const_reverse_iterator(begin()); }
161       // 23.2.4.2 capacity:
162       using _Base::size;
163       using _Base::max_size;
165       void
166       resize(size_type __sz, _Tp __c = _Tp())
167       {
168         bool __realloc = _M_requires_reallocation(__sz);
169         if (__sz < this->size())
170           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
171         _Base::resize(__sz, __c);
172         if (__realloc)
173           this->_M_invalidate_all();
174       }
176       using _Base::capacity;
177       using _Base::empty;
179       void
180       reserve(size_type __n)
181       {
182         bool __realloc = _M_requires_reallocation(__n);
183         _Base::reserve(__n);
184         if (__n > _M_guaranteed_capacity)
185           _M_guaranteed_capacity = __n;
186         if (__realloc)
187           this->_M_invalidate_all();
188       }
190       // element access:
191       reference
192       operator[](size_type __n)
193       {
194         __glibcxx_check_subscript(__n);
195         return _M_base()[__n];
196       }
198       const_reference
199       operator[](size_type __n) const
200       {
201         __glibcxx_check_subscript(__n);
202         return _M_base()[__n];
203       }
205       using _Base::at;
207       reference
208       front()
209       {
210         __glibcxx_check_nonempty();
211         return _Base::front();
212       }
214       const_reference
215       front() const
216       {
217         __glibcxx_check_nonempty();
218         return _Base::front();
219       }
221       reference
222       back()
223       {
224         __glibcxx_check_nonempty();
225         return _Base::back();
226       }
228       const_reference
229       back() const
230       {
231         __glibcxx_check_nonempty();
232         return _Base::back();
233       }
235       // _GLIBCXX_RESOLVE_LIB_DEFECTS
236       // DR 464. Suggestion for new member functions in standard containers.
237       using _Base::data;
239       // 23.2.4.3 modifiers:
240       void
241       push_back(const _Tp& __x)
242       {
243         bool __realloc = _M_requires_reallocation(this->size() + 1);
244         _Base::push_back(__x);
245         if (__realloc)
246           this->_M_invalidate_all();
247         _M_update_guaranteed_capacity();
248       }
250       void
251       pop_back()
252       {
253         __glibcxx_check_nonempty();
254         iterator __victim = end() - 1;
255         __victim._M_invalidate();
256         _Base::pop_back();
257       }
259       iterator
260       insert(iterator __position, const _Tp& __x)
261       {
262         __glibcxx_check_insert(__position);
263         bool __realloc = _M_requires_reallocation(this->size() + 1);
264         difference_type __offset = __position - begin();
265         typename _Base::iterator __res = _Base::insert(__position.base(),__x);
266         if (__realloc)
267           this->_M_invalidate_all();
268         else
269           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
270         _M_update_guaranteed_capacity();
271         return iterator(__res, this);
272       }
274       void
275       insert(iterator __position, size_type __n, const _Tp& __x)
276       {
277         __glibcxx_check_insert(__position);
278         bool __realloc = _M_requires_reallocation(this->size() + __n);
279         difference_type __offset = __position - begin();
280         _Base::insert(__position.base(), __n, __x);
281         if (__realloc)
282           this->_M_invalidate_all();
283         else
284           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
285         _M_update_guaranteed_capacity();
286       }
288       template<class _InputIterator>
289         void
290         insert(iterator __position,
291                _InputIterator __first, _InputIterator __last)
292         {
293           __glibcxx_check_insert_range(__position, __first, __last);
295           /* Hard to guess if invalidation will occur, because __last
296              - __first can't be calculated in all cases, so we just
297              punt here by checking if it did occur. */
298           typename _Base::iterator __old_begin = _M_base().begin();
299           difference_type __offset = __position - begin();
300           _Base::insert(__position.base(), __first, __last);
302           if (_M_base().begin() != __old_begin)
303             this->_M_invalidate_all();
304           else
305             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
306           _M_update_guaranteed_capacity();
307         }
309       iterator
310       erase(iterator __position)
311       {
312         __glibcxx_check_erase(__position);
313         difference_type __offset = __position - begin();
314         typename _Base::iterator __res = _Base::erase(__position.base());
315         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
316         return iterator(__res, this);
317       }
319       iterator
320       erase(iterator __first, iterator __last)
321       {
322         // _GLIBCXX_RESOLVE_LIB_DEFECTS
323         // 151. can't currently clear() empty container
324         __glibcxx_check_erase_range(__first, __last);
326         difference_type __offset = __first - begin();
327         typename _Base::iterator __res = _Base::erase(__first.base(),
328                                                          __last.base());
329         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
330         return iterator(__res, this);
331       }
333       void
334       swap(vector<_Tp,_Allocator>& __x)
335       {
336         _Base::swap(__x);
337         this->_M_swap(__x);
338         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
339       }
341       void
342       clear()
343       {
344         _Base::clear();
345         this->_M_invalidate_all();
346         _M_guaranteed_capacity = 0;
347       }
349       _Base&
350       _M_base() { return *this; }
352       const _Base&
353       _M_base() const { return *this; }
355     private:
356       size_type _M_guaranteed_capacity;
358       bool
359       _M_requires_reallocation(size_type __elements)
360       {
361 #ifdef _GLIBCXX_DEBUG_PEDANTIC
362         return __elements > this->capacity();
363 #else
364         return __elements > _M_guaranteed_capacity;
365 #endif
366       }
368       void
369       _M_update_guaranteed_capacity()
370       {
371         if (this->size() > _M_guaranteed_capacity)
372           _M_guaranteed_capacity = this->size();
373       }
374     };
376   template<typename _Tp, typename _Alloc>
377     inline bool
378     operator==(const vector<_Tp, _Alloc>& __lhs,
379                const vector<_Tp, _Alloc>& __rhs)
380     { return __lhs._M_base() == __rhs._M_base(); }
382   template<typename _Tp, typename _Alloc>
383     inline bool
384     operator!=(const vector<_Tp, _Alloc>& __lhs,
385                const vector<_Tp, _Alloc>& __rhs)
386     { return __lhs._M_base() != __rhs._M_base(); }
388   template<typename _Tp, typename _Alloc>
389     inline bool
390     operator<(const vector<_Tp, _Alloc>& __lhs,
391               const vector<_Tp, _Alloc>& __rhs)
392     { return __lhs._M_base() < __rhs._M_base(); }
394   template<typename _Tp, typename _Alloc>
395     inline bool
396     operator<=(const vector<_Tp, _Alloc>& __lhs,
397                const vector<_Tp, _Alloc>& __rhs)
398     { return __lhs._M_base() <= __rhs._M_base(); }
400   template<typename _Tp, typename _Alloc>
401     inline bool
402     operator>=(const vector<_Tp, _Alloc>& __lhs,
403                const vector<_Tp, _Alloc>& __rhs)
404     { return __lhs._M_base() >= __rhs._M_base(); }
406   template<typename _Tp, typename _Alloc>
407     inline bool
408     operator>(const vector<_Tp, _Alloc>& __lhs,
409               const vector<_Tp, _Alloc>& __rhs)
410     { return __lhs._M_base() > __rhs._M_base(); }
412   template<typename _Tp, typename _Alloc>
413     inline void
414     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
415     { __lhs.swap(__rhs); }
416 } // namespace __gnu_debug_def
417 } // namespace std
419 #endif