Merged with trunk at revision 155767
[official-gcc.git] / libstdc++-v3 / include / debug / vector
blobca326e4194dfade42c89b02cd1add860d13cb2f7
1 // Debugging vector implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
26 /** @file debug/vector
27  *  This file is a GNU debug extension to the Standard C++ Library.
28  */
30 #ifndef _GLIBCXX_DEBUG_VECTOR
31 #define _GLIBCXX_DEBUG_VECTOR 1
33 #include <vector>
34 #include <utility>
35 #include <debug/safe_sequence.h>
36 #include <debug/safe_iterator.h>
38 namespace std
40 namespace __debug
42   /// Class std::vector with safety/checking/debug instrumentation.
43   template<typename _Tp,
44            typename _Allocator = std::allocator<_Tp> >
45     class vector
46     : public _GLIBCXX_STD_D::vector<_Tp, _Allocator>,
47       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
48     {
49       typedef _GLIBCXX_STD_D::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& __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 #ifdef __GXX_EXPERIMENTAL_CXX0X__
98       vector(vector&& __x)
99       : _Base(std::forward<vector>(__x)), _Safe_base(),
100         _M_guaranteed_capacity(this->size())
101       {
102         this->_M_swap(__x);
103         __x._M_guaranteed_capacity = 0;
104       }
106       vector(initializer_list<value_type> __l,
107              const allocator_type& __a = allocator_type())
108       : _Base(__l, __a), _Safe_base(),
109         _M_guaranteed_capacity(__l.size()) { }
110 #endif
112       ~vector() { }
114       vector&
115       operator=(const vector& __x)
116       {
117         static_cast<_Base&>(*this) = __x;
118         this->_M_invalidate_all();
119         _M_update_guaranteed_capacity();
120         return *this;
121       }
123 #ifdef __GXX_EXPERIMENTAL_CXX0X__
124       vector&
125       operator=(vector&& __x)
126       {
127         // NB: DR 1204.
128         // NB: DR 675.
129         clear();
130         swap(__x);
131         return *this;
132       }
134       vector&
135       operator=(initializer_list<value_type> __l)
136       {
137         static_cast<_Base&>(*this) = __l;
138         this->_M_invalidate_all();
139         _M_update_guaranteed_capacity();
140         return *this;
141       }
142 #endif
144       template<typename _InputIterator>
145         void
146         assign(_InputIterator __first, _InputIterator __last)
147         {
148           __glibcxx_check_valid_range(__first, __last);
149           _Base::assign(__first, __last);
150           this->_M_invalidate_all();
151           _M_update_guaranteed_capacity();
152         }
154       void
155       assign(size_type __n, const _Tp& __u)
156       {
157         _Base::assign(__n, __u);
158         this->_M_invalidate_all();
159         _M_update_guaranteed_capacity();
160       }
162 #ifdef __GXX_EXPERIMENTAL_CXX0X__
163       void
164       assign(initializer_list<value_type> __l)
165       {
166         _Base::assign(__l);
167         this->_M_invalidate_all();
168         _M_update_guaranteed_capacity();
169       }
170 #endif
172       using _Base::get_allocator;
174       // iterators:
175       iterator
176       begin()
177       { return iterator(_Base::begin(), this); }
179       const_iterator
180       begin() const
181       { return const_iterator(_Base::begin(), this); }
183       iterator
184       end()
185       { return iterator(_Base::end(), this); }
187       const_iterator
188       end() const
189       { return const_iterator(_Base::end(), this); }
191       reverse_iterator
192       rbegin()
193       { return reverse_iterator(end()); }
195       const_reverse_iterator
196       rbegin() const
197       { return const_reverse_iterator(end()); }
199       reverse_iterator
200       rend()
201       { return reverse_iterator(begin()); }
203       const_reverse_iterator
204       rend() const
205       { return const_reverse_iterator(begin()); }
207 #ifdef __GXX_EXPERIMENTAL_CXX0X__
208       const_iterator
209       cbegin() const
210       { return const_iterator(_Base::begin(), this); }
212       const_iterator
213       cend() const
214       { return const_iterator(_Base::end(), this); }
216       const_reverse_iterator
217       crbegin() const
218       { return const_reverse_iterator(end()); }
220       const_reverse_iterator
221       crend() const
222       { return const_reverse_iterator(begin()); }
223 #endif
225       // 23.2.4.2 capacity:
226       using _Base::size;
227       using _Base::max_size;
229       void
230       resize(size_type __sz, _Tp __c = _Tp())
231       {
232         bool __realloc = _M_requires_reallocation(__sz);
233         if (__sz < this->size())
234           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
235         _Base::resize(__sz, __c);
236         if (__realloc)
237           this->_M_invalidate_all();
238       }
240 #ifdef __GXX_EXPERIMENTAL_CXX0X__
241       using _Base::shrink_to_fit;
242 #endif
244       size_type
245       capacity() const
246       {
247 #ifdef _GLIBCXX_DEBUG_PEDANTIC
248         return _M_guaranteed_capacity;
249 #else
250         return _Base::capacity();
251 #endif
252       }
254       using _Base::empty;
256       void
257       reserve(size_type __n)
258       {
259         bool __realloc = _M_requires_reallocation(__n);
260         _Base::reserve(__n);
261         if (__n > _M_guaranteed_capacity)
262           _M_guaranteed_capacity = __n;
263         if (__realloc)
264           this->_M_invalidate_all();
265       }
267       // element access:
268       reference
269       operator[](size_type __n)
270       {
271         __glibcxx_check_subscript(__n);
272         return _M_base()[__n];
273       }
275       const_reference
276       operator[](size_type __n) const
277       {
278         __glibcxx_check_subscript(__n);
279         return _M_base()[__n];
280       }
282       using _Base::at;
284       reference
285       front()
286       {
287         __glibcxx_check_nonempty();
288         return _Base::front();
289       }
291       const_reference
292       front() const
293       {
294         __glibcxx_check_nonempty();
295         return _Base::front();
296       }
298       reference
299       back()
300       {
301         __glibcxx_check_nonempty();
302         return _Base::back();
303       }
305       const_reference
306       back() const
307       {
308         __glibcxx_check_nonempty();
309         return _Base::back();
310       }
312       // _GLIBCXX_RESOLVE_LIB_DEFECTS
313       // DR 464. Suggestion for new member functions in standard containers.
314       using _Base::data;
316       // 23.2.4.3 modifiers:
317       void
318       push_back(const _Tp& __x)
319       {
320         bool __realloc = _M_requires_reallocation(this->size() + 1);
321         _Base::push_back(__x);
322         if (__realloc)
323           this->_M_invalidate_all();
324         _M_update_guaranteed_capacity();
325       }
327 #ifdef __GXX_EXPERIMENTAL_CXX0X__
328       template<typename _Up = _Tp>
329         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
330                                         void>::__type
331         push_back(_Tp&& __x)
332         { emplace_back(std::move(__x)); }
334       template<typename... _Args>
335         void
336         emplace_back(_Args&&... __args)
337         {
338           bool __realloc = _M_requires_reallocation(this->size() + 1);
339           _Base::emplace_back(std::forward<_Args>(__args)...);
340           if (__realloc)
341             this->_M_invalidate_all();
342           _M_update_guaranteed_capacity();
343         }
344 #endif
346       void
347       pop_back()
348       {
349         __glibcxx_check_nonempty();
350         iterator __victim = end() - 1;
351         __victim._M_invalidate();
352         _Base::pop_back();
353       }
355 #ifdef __GXX_EXPERIMENTAL_CXX0X__
356       template<typename... _Args>
357         iterator
358         emplace(iterator __position, _Args&&... __args)
359         {
360           __glibcxx_check_insert(__position);
361           bool __realloc = _M_requires_reallocation(this->size() + 1);
362           difference_type __offset = __position - begin();
363           typename _Base::iterator __res = _Base::emplace(__position.base(),
364                                             std::forward<_Args>(__args)...);
365           if (__realloc)
366             this->_M_invalidate_all();
367           else
368             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
369           _M_update_guaranteed_capacity();
370           return iterator(__res, this);
371         }
372 #endif
374       iterator
375       insert(iterator __position, const _Tp& __x)
376       {
377         __glibcxx_check_insert(__position);
378         bool __realloc = _M_requires_reallocation(this->size() + 1);
379         difference_type __offset = __position - begin();
380         typename _Base::iterator __res = _Base::insert(__position.base(),__x);
381         if (__realloc)
382           this->_M_invalidate_all();
383         else
384           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
385         _M_update_guaranteed_capacity();
386         return iterator(__res, this);
387       }
389 #ifdef __GXX_EXPERIMENTAL_CXX0X__
390       template<typename _Up = _Tp>
391         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
392                                         iterator>::__type
393         insert(iterator __position, _Tp&& __x)
394         { return emplace(__position, std::move(__x)); }
396       void
397       insert(iterator __position, initializer_list<value_type> __l)
398       { this->insert(__position, __l.begin(), __l.end()); }
399 #endif
401       void
402       insert(iterator __position, size_type __n, const _Tp& __x)
403       {
404         __glibcxx_check_insert(__position);
405         bool __realloc = _M_requires_reallocation(this->size() + __n);
406         difference_type __offset = __position - begin();
407         _Base::insert(__position.base(), __n, __x);
408         if (__realloc)
409           this->_M_invalidate_all();
410         else
411           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
412         _M_update_guaranteed_capacity();
413       }
415       template<class _InputIterator>
416         void
417         insert(iterator __position,
418                _InputIterator __first, _InputIterator __last)
419         {
420           __glibcxx_check_insert_range(__position, __first, __last);
422           /* Hard to guess if invalidation will occur, because __last
423              - __first can't be calculated in all cases, so we just
424              punt here by checking if it did occur. */
425           typename _Base::iterator __old_begin = _M_base().begin();
426           difference_type __offset = __position - begin();
427           _Base::insert(__position.base(), __first, __last);
429           if (_M_base().begin() != __old_begin)
430             this->_M_invalidate_all();
431           else
432             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
433           _M_update_guaranteed_capacity();
434         }
436       iterator
437       erase(iterator __position)
438       {
439         __glibcxx_check_erase(__position);
440         difference_type __offset = __position - begin();
441         typename _Base::iterator __res = _Base::erase(__position.base());
442         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
443         return iterator(__res, this);
444       }
446       iterator
447       erase(iterator __first, iterator __last)
448       {
449         // _GLIBCXX_RESOLVE_LIB_DEFECTS
450         // 151. can't currently clear() empty container
451         __glibcxx_check_erase_range(__first, __last);
453         difference_type __offset = __first - begin();
454         typename _Base::iterator __res = _Base::erase(__first.base(),
455                                                          __last.base());
456         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
457         return iterator(__res, this);
458       }
460       void
461       swap(vector& __x)
462       {
463         _Base::swap(__x);
464         this->_M_swap(__x);
465         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
466       }
468       void
469       clear()
470       {
471         _Base::clear();
472         this->_M_invalidate_all();
473         _M_guaranteed_capacity = 0;
474       }
476       _Base&
477       _M_base() { return *this; }
479       const _Base&
480       _M_base() const { return *this; }
482     private:
483       size_type _M_guaranteed_capacity;
485       bool
486       _M_requires_reallocation(size_type __elements)
487       { return __elements > this->capacity(); }
489       void
490       _M_update_guaranteed_capacity()
491       {
492         if (this->size() > _M_guaranteed_capacity)
493           _M_guaranteed_capacity = this->size();
494       }
495     };
497   template<typename _Tp, typename _Alloc>
498     inline bool
499     operator==(const vector<_Tp, _Alloc>& __lhs,
500                const vector<_Tp, _Alloc>& __rhs)
501     { return __lhs._M_base() == __rhs._M_base(); }
503   template<typename _Tp, typename _Alloc>
504     inline bool
505     operator!=(const vector<_Tp, _Alloc>& __lhs,
506                const vector<_Tp, _Alloc>& __rhs)
507     { return __lhs._M_base() != __rhs._M_base(); }
509   template<typename _Tp, typename _Alloc>
510     inline bool
511     operator<(const vector<_Tp, _Alloc>& __lhs,
512               const vector<_Tp, _Alloc>& __rhs)
513     { return __lhs._M_base() < __rhs._M_base(); }
515   template<typename _Tp, typename _Alloc>
516     inline bool
517     operator<=(const vector<_Tp, _Alloc>& __lhs,
518                const vector<_Tp, _Alloc>& __rhs)
519     { return __lhs._M_base() <= __rhs._M_base(); }
521   template<typename _Tp, typename _Alloc>
522     inline bool
523     operator>=(const vector<_Tp, _Alloc>& __lhs,
524                const vector<_Tp, _Alloc>& __rhs)
525     { return __lhs._M_base() >= __rhs._M_base(); }
527   template<typename _Tp, typename _Alloc>
528     inline bool
529     operator>(const vector<_Tp, _Alloc>& __lhs,
530               const vector<_Tp, _Alloc>& __rhs)
531     { return __lhs._M_base() > __rhs._M_base(); }
533   template<typename _Tp, typename _Alloc>
534     inline void
535     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
536     { __lhs.swap(__rhs); }
538 } // namespace __debug
539 } // namespace std
541 #endif