2008-05-30 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libstdc++-v3 / include / debug / vector
blob7945b54591e5171153664ff241dc51054479f8fb
1 // Debugging vector implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
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 /** @file debug/vector
32  *  This file is a GNU debug extension to the Standard C++ Library.
33  */
35 #ifndef _GLIBCXX_DEBUG_VECTOR
36 #define _GLIBCXX_DEBUG_VECTOR 1
38 #include <vector>
39 #include <utility>
40 #include <debug/safe_sequence.h>
41 #include <debug/safe_iterator.h>
43 namespace std
45 namespace __debug
47   template<typename _Tp,
48            typename _Allocator = std::allocator<_Tp> >
49     class vector
50     : public _GLIBCXX_STD_D::vector<_Tp, _Allocator>,
51       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
52     {
53       typedef _GLIBCXX_STD_D::vector<_Tp, _Allocator> _Base;
54       typedef __gnu_debug::_Safe_sequence<vector>              _Safe_base;
56       typedef typename _Base::const_iterator _Base_const_iterator;
57       typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
59     public:
60       typedef typename _Base::reference             reference;
61       typedef typename _Base::const_reference       const_reference;
63       typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,vector>
64       iterator;
65       typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,vector>
66       const_iterator;
68       typedef typename _Base::size_type             size_type;
69       typedef typename _Base::difference_type       difference_type;
71       typedef _Tp                                   value_type;
72       typedef _Allocator                            allocator_type;
73       typedef typename _Base::pointer               pointer;
74       typedef typename _Base::const_pointer         const_pointer;
75       typedef std::reverse_iterator<iterator>       reverse_iterator;
76       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
78       // 23.2.4.1 construct/copy/destroy:
79       explicit vector(const _Allocator& __a = _Allocator())
80       : _Base(__a), _M_guaranteed_capacity(0) { }
82       explicit vector(size_type __n, const _Tp& __value = _Tp(),
83                       const _Allocator& __a = _Allocator())
84       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
86       template<class _InputIterator>
87         vector(_InputIterator __first, _InputIterator __last,
88                const _Allocator& __a = _Allocator())
89         : _Base(__gnu_debug::__check_valid_range(__first, __last),
90                 __last, __a),
91           _M_guaranteed_capacity(0)
92         { _M_update_guaranteed_capacity(); }
94       vector(const vector& __x)
95       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
97       /// Construction from a release-mode vector
98       vector(const _Base& __x)
99       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
101 #ifdef __GXX_EXPERIMENTAL_CXX0X__
102       vector(vector&& __x)
103       : _Base(std::forward<vector>(__x)), _Safe_base(),
104         _M_guaranteed_capacity(this->size())
105       {
106         this->_M_swap(__x);
107         __x._M_guaranteed_capacity = 0;
108       }
109 #endif
111       ~vector() { }
113       vector&
114       operator=(const vector& __x)
115       {
116         static_cast<_Base&>(*this) = __x;
117         this->_M_invalidate_all();
118         _M_update_guaranteed_capacity();
119         return *this;
120       }
122 #ifdef __GXX_EXPERIMENTAL_CXX0X__
123       vector&
124       operator=(vector&& __x)
125       {
126         // NB: DR 675.
127         clear();
128         swap(__x);
129         return *this;
130       }
131 #endif
133       template<typename _InputIterator>
134         void
135         assign(_InputIterator __first, _InputIterator __last)
136         {
137           __glibcxx_check_valid_range(__first, __last);
138           _Base::assign(__first, __last);
139           this->_M_invalidate_all();
140           _M_update_guaranteed_capacity();
141         }
143       void
144       assign(size_type __n, const _Tp& __u)
145       {
146         _Base::assign(__n, __u);
147         this->_M_invalidate_all();
148         _M_update_guaranteed_capacity();
149       }
151       using _Base::get_allocator;
153       // iterators:
154       iterator
155       begin()
156       { return iterator(_Base::begin(), this); }
158       const_iterator
159       begin() const
160       { return const_iterator(_Base::begin(), this); }
162       iterator
163       end()
164       { return iterator(_Base::end(), this); }
166       const_iterator
167       end() const
168       { return const_iterator(_Base::end(), this); }
170       reverse_iterator
171       rbegin()
172       { return reverse_iterator(end()); }
174       const_reverse_iterator
175       rbegin() const
176       { return const_reverse_iterator(end()); }
178       reverse_iterator
179       rend()
180       { return reverse_iterator(begin()); }
182       const_reverse_iterator
183       rend() const
184       { return const_reverse_iterator(begin()); }
186 #ifdef __GXX_EXPERIMENTAL_CXX0X__
187       const_iterator
188       cbegin() const
189       { return const_iterator(_Base::begin(), this); }
191       const_iterator
192       cend() const
193       { return const_iterator(_Base::end(), this); }
195       const_reverse_iterator
196       crbegin() const
197       { return const_reverse_iterator(end()); }
199       const_reverse_iterator
200       crend() const
201       { return const_reverse_iterator(begin()); }
202 #endif
204       // 23.2.4.2 capacity:
205       using _Base::size;
206       using _Base::max_size;
208       void
209       resize(size_type __sz, _Tp __c = _Tp())
210       {
211         bool __realloc = _M_requires_reallocation(__sz);
212         if (__sz < this->size())
213           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
214         _Base::resize(__sz, __c);
215         if (__realloc)
216           this->_M_invalidate_all();
217       }
219       size_type
220       capacity() const
221       {
222 #ifdef _GLIBCXX_DEBUG_PEDANTIC
223         return _M_guaranteed_capacity;
224 #else
225         return _Base::capacity();
226 #endif
227       }
229       using _Base::empty;
231       void
232       reserve(size_type __n)
233       {
234         bool __realloc = _M_requires_reallocation(__n);
235         _Base::reserve(__n);
236         if (__n > _M_guaranteed_capacity)
237           _M_guaranteed_capacity = __n;
238         if (__realloc)
239           this->_M_invalidate_all();
240       }
242       // element access:
243       reference
244       operator[](size_type __n)
245       {
246         __glibcxx_check_subscript(__n);
247         return _M_base()[__n];
248       }
250       const_reference
251       operator[](size_type __n) const
252       {
253         __glibcxx_check_subscript(__n);
254         return _M_base()[__n];
255       }
257       using _Base::at;
259       reference
260       front()
261       {
262         __glibcxx_check_nonempty();
263         return _Base::front();
264       }
266       const_reference
267       front() const
268       {
269         __glibcxx_check_nonempty();
270         return _Base::front();
271       }
273       reference
274       back()
275       {
276         __glibcxx_check_nonempty();
277         return _Base::back();
278       }
280       const_reference
281       back() const
282       {
283         __glibcxx_check_nonempty();
284         return _Base::back();
285       }
287       // _GLIBCXX_RESOLVE_LIB_DEFECTS
288       // DR 464. Suggestion for new member functions in standard containers.
289       using _Base::data;
291       // 23.2.4.3 modifiers:
292 #ifndef __GXX_EXPERIMENTAL_CXX0X__
293       void
294       push_back(const _Tp& __x)
295       {
296         bool __realloc = _M_requires_reallocation(this->size() + 1);
297         _Base::push_back(__x);
298         if (__realloc)
299           this->_M_invalidate_all();
300         _M_update_guaranteed_capacity();
301       }
302 #else
303       template<typename... _Args>
304         void
305         push_back(_Args&&... __args)
306         {
307           bool __realloc = _M_requires_reallocation(this->size() + 1);
308           _Base::push_back(std::forward<_Args>(__args)...);
309           if (__realloc)
310             this->_M_invalidate_all();
311           _M_update_guaranteed_capacity();
312         }
313 #endif
315       void
316       pop_back()
317       {
318         __glibcxx_check_nonempty();
319         iterator __victim = end() - 1;
320         __victim._M_invalidate();
321         _Base::pop_back();
322       }
324 #ifdef __GXX_EXPERIMENTAL_CXX0X__
325       template<typename... _Args>
326         iterator
327         emplace(iterator __position, _Args&&... __args)
328         {
329           __glibcxx_check_insert(__position);
330           bool __realloc = _M_requires_reallocation(this->size() + 1);
331           difference_type __offset = __position - begin();
332           typename _Base::iterator __res = _Base::emplace(__position.base(),
333                                             std::forward<_Args>(__args)...);
334           if (__realloc)
335             this->_M_invalidate_all();
336           else
337             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
338           _M_update_guaranteed_capacity();
339           return iterator(__res, this);
340         }
341 #endif
343       iterator
344       insert(iterator __position, const _Tp& __x)
345       {
346         __glibcxx_check_insert(__position);
347         bool __realloc = _M_requires_reallocation(this->size() + 1);
348         difference_type __offset = __position - begin();
349         typename _Base::iterator __res = _Base::insert(__position.base(),__x);
350         if (__realloc)
351           this->_M_invalidate_all();
352         else
353           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
354         _M_update_guaranteed_capacity();
355         return iterator(__res, this);
356       }
358 #ifdef __GXX_EXPERIMENTAL_CXX0X__
359       iterator
360       insert(iterator __position, _Tp&& __x)
361       { return emplace(__position, std::move(__x)); }
362 #endif
364       void
365       insert(iterator __position, size_type __n, const _Tp& __x)
366       {
367         __glibcxx_check_insert(__position);
368         bool __realloc = _M_requires_reallocation(this->size() + __n);
369         difference_type __offset = __position - begin();
370         _Base::insert(__position.base(), __n, __x);
371         if (__realloc)
372           this->_M_invalidate_all();
373         else
374           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
375         _M_update_guaranteed_capacity();
376       }
378       template<class _InputIterator>
379         void
380         insert(iterator __position,
381                _InputIterator __first, _InputIterator __last)
382         {
383           __glibcxx_check_insert_range(__position, __first, __last);
385           /* Hard to guess if invalidation will occur, because __last
386              - __first can't be calculated in all cases, so we just
387              punt here by checking if it did occur. */
388           typename _Base::iterator __old_begin = _M_base().begin();
389           difference_type __offset = __position - begin();
390           _Base::insert(__position.base(), __first, __last);
392           if (_M_base().begin() != __old_begin)
393             this->_M_invalidate_all();
394           else
395             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
396           _M_update_guaranteed_capacity();
397         }
399       iterator
400       erase(iterator __position)
401       {
402         __glibcxx_check_erase(__position);
403         difference_type __offset = __position - begin();
404         typename _Base::iterator __res = _Base::erase(__position.base());
405         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
406         return iterator(__res, this);
407       }
409       iterator
410       erase(iterator __first, iterator __last)
411       {
412         // _GLIBCXX_RESOLVE_LIB_DEFECTS
413         // 151. can't currently clear() empty container
414         __glibcxx_check_erase_range(__first, __last);
416         difference_type __offset = __first - begin();
417         typename _Base::iterator __res = _Base::erase(__first.base(),
418                                                          __last.base());
419         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
420         return iterator(__res, this);
421       }
423       void
424 #ifdef __GXX_EXPERIMENTAL_CXX0X__
425       swap(vector&& __x)
426 #else
427       swap(vector& __x)
428 #endif
429       {
430         _Base::swap(__x);
431         this->_M_swap(__x);
432         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
433       }
435       void
436       clear()
437       {
438         _Base::clear();
439         this->_M_invalidate_all();
440         _M_guaranteed_capacity = 0;
441       }
443       _Base&
444       _M_base() { return *this; }
446       const _Base&
447       _M_base() const { return *this; }
449     private:
450       size_type _M_guaranteed_capacity;
452       bool
453       _M_requires_reallocation(size_type __elements)
454       { return __elements > this->capacity(); }
456       void
457       _M_update_guaranteed_capacity()
458       {
459         if (this->size() > _M_guaranteed_capacity)
460           _M_guaranteed_capacity = this->size();
461       }
462     };
464   template<typename _Tp, typename _Alloc>
465     inline bool
466     operator==(const vector<_Tp, _Alloc>& __lhs,
467                const vector<_Tp, _Alloc>& __rhs)
468     { return __lhs._M_base() == __rhs._M_base(); }
470   template<typename _Tp, typename _Alloc>
471     inline bool
472     operator!=(const vector<_Tp, _Alloc>& __lhs,
473                const vector<_Tp, _Alloc>& __rhs)
474     { return __lhs._M_base() != __rhs._M_base(); }
476   template<typename _Tp, typename _Alloc>
477     inline bool
478     operator<(const vector<_Tp, _Alloc>& __lhs,
479               const vector<_Tp, _Alloc>& __rhs)
480     { return __lhs._M_base() < __rhs._M_base(); }
482   template<typename _Tp, typename _Alloc>
483     inline bool
484     operator<=(const vector<_Tp, _Alloc>& __lhs,
485                const vector<_Tp, _Alloc>& __rhs)
486     { return __lhs._M_base() <= __rhs._M_base(); }
488   template<typename _Tp, typename _Alloc>
489     inline bool
490     operator>=(const vector<_Tp, _Alloc>& __lhs,
491                const vector<_Tp, _Alloc>& __rhs)
492     { return __lhs._M_base() >= __rhs._M_base(); }
494   template<typename _Tp, typename _Alloc>
495     inline bool
496     operator>(const vector<_Tp, _Alloc>& __lhs,
497               const vector<_Tp, _Alloc>& __rhs)
498     { return __lhs._M_base() > __rhs._M_base(); }
500   template<typename _Tp, typename _Alloc>
501     inline void
502     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
503     { __lhs.swap(__rhs); }
505 #ifdef __GXX_EXPERIMENTAL_CXX0X__
506   template<typename _Tp, typename _Alloc>
507     inline void
508     swap(vector<_Tp, _Alloc>&& __lhs, vector<_Tp, _Alloc>& __rhs)
509     { __lhs.swap(__rhs); }
511   template<typename _Tp, typename _Alloc>
512     inline void
513     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>&& __rhs)
514     { __lhs.swap(__rhs); }
515 #endif
517 } // namespace __debug
518 } // namespace std
520 #endif