Merge from mainline (163495:164578).
[official-gcc/graphite-test-results.git] / libstdc++-v3 / include / debug / vector
blob9004f2902aeaedffb79561e90dce0edc159fe5d1
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
76       vector(const _Allocator& __a = _Allocator())
77       : _Base(__a), _M_guaranteed_capacity(0) { }
79 #ifdef __GXX_EXPERIMENTAL_CXX0X__
80       explicit
81       vector(size_type __n)
82       : _Base(__n), _M_guaranteed_capacity(__n) { }
84       vector(size_type __n, const _Tp& __value,
85              const _Allocator& __a = _Allocator())
86       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
87 #else
88       explicit
89       vector(size_type __n, const _Tp& __value = _Tp(),
90              const _Allocator& __a = _Allocator())
91       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
92 #endif
94       template<class _InputIterator>
95         vector(_InputIterator __first, _InputIterator __last,
96                const _Allocator& __a = _Allocator())
97         : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
98                                                                      __last)),
99                 __gnu_debug::__base(__last), __a),
100           _M_guaranteed_capacity(0)
101         { _M_update_guaranteed_capacity(); }
103       vector(const vector& __x)
104       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
106       /// Construction from a release-mode vector
107       vector(const _Base& __x)
108       : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { }
110 #ifdef __GXX_EXPERIMENTAL_CXX0X__
111       vector(vector&& __x)
112       : _Base(std::move(__x)), _Safe_base(),
113         _M_guaranteed_capacity(this->size())
114       {
115         this->_M_swap(__x);
116         __x._M_guaranteed_capacity = 0;
117       }
119       vector(initializer_list<value_type> __l,
120              const allocator_type& __a = allocator_type())
121       : _Base(__l, __a), _Safe_base(),
122         _M_guaranteed_capacity(__l.size()) { }
123 #endif
125       ~vector() { }
127       vector&
128       operator=(const vector& __x)
129       {
130         static_cast<_Base&>(*this) = __x;
131         this->_M_invalidate_all();
132         _M_update_guaranteed_capacity();
133         return *this;
134       }
136 #ifdef __GXX_EXPERIMENTAL_CXX0X__
137       vector&
138       operator=(vector&& __x)
139       {
140         // NB: DR 1204.
141         // NB: DR 675.
142         clear();
143         swap(__x);
144         return *this;
145       }
147       vector&
148       operator=(initializer_list<value_type> __l)
149       {
150         static_cast<_Base&>(*this) = __l;
151         this->_M_invalidate_all();
152         _M_update_guaranteed_capacity();
153         return *this;
154       }
155 #endif
157       template<typename _InputIterator>
158         void
159         assign(_InputIterator __first, _InputIterator __last)
160         {
161           __glibcxx_check_valid_range(__first, __last);
162           _Base::assign(__gnu_debug::__base(__first),
163                         __gnu_debug::__base(__last));
164           this->_M_invalidate_all();
165           _M_update_guaranteed_capacity();
166         }
168       void
169       assign(size_type __n, const _Tp& __u)
170       {
171         _Base::assign(__n, __u);
172         this->_M_invalidate_all();
173         _M_update_guaranteed_capacity();
174       }
176 #ifdef __GXX_EXPERIMENTAL_CXX0X__
177       void
178       assign(initializer_list<value_type> __l)
179       {
180         _Base::assign(__l);
181         this->_M_invalidate_all();
182         _M_update_guaranteed_capacity();
183       }
184 #endif
186       using _Base::get_allocator;
188       // iterators:
189       iterator
190       begin()
191       { return iterator(_Base::begin(), this); }
193       const_iterator
194       begin() const
195       { return const_iterator(_Base::begin(), this); }
197       iterator
198       end()
199       { return iterator(_Base::end(), this); }
201       const_iterator
202       end() const
203       { return const_iterator(_Base::end(), this); }
205       reverse_iterator
206       rbegin()
207       { return reverse_iterator(end()); }
209       const_reverse_iterator
210       rbegin() const
211       { return const_reverse_iterator(end()); }
213       reverse_iterator
214       rend()
215       { return reverse_iterator(begin()); }
217       const_reverse_iterator
218       rend() const
219       { return const_reverse_iterator(begin()); }
221 #ifdef __GXX_EXPERIMENTAL_CXX0X__
222       const_iterator
223       cbegin() const
224       { return const_iterator(_Base::begin(), this); }
226       const_iterator
227       cend() const
228       { return const_iterator(_Base::end(), this); }
230       const_reverse_iterator
231       crbegin() const
232       { return const_reverse_iterator(end()); }
234       const_reverse_iterator
235       crend() const
236       { return const_reverse_iterator(begin()); }
237 #endif
239       // 23.2.4.2 capacity:
240       using _Base::size;
241       using _Base::max_size;
243 #ifdef __GXX_EXPERIMENTAL_CXX0X__
244       void
245       resize(size_type __sz)
246       {
247         bool __realloc = _M_requires_reallocation(__sz);
248         if (__sz < this->size())
249           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
250         _Base::resize(__sz);
251         if (__realloc)
252           this->_M_invalidate_all();
253         _M_update_guaranteed_capacity();
254       }
256       void
257       resize(size_type __sz, const _Tp& __c)
258       {
259         bool __realloc = _M_requires_reallocation(__sz);
260         if (__sz < this->size())
261           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
262         _Base::resize(__sz, __c);
263         if (__realloc)
264           this->_M_invalidate_all();
265         _M_update_guaranteed_capacity();
266       }
267 #else
268       void
269       resize(size_type __sz, _Tp __c = _Tp())
270       {
271         bool __realloc = _M_requires_reallocation(__sz);
272         if (__sz < this->size())
273           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
274         _Base::resize(__sz, __c);
275         if (__realloc)
276           this->_M_invalidate_all();
277         _M_update_guaranteed_capacity();
278       }
279 #endif
281 #ifdef __GXX_EXPERIMENTAL_CXX0X__
282       using _Base::shrink_to_fit;
283 #endif
285       size_type
286       capacity() const
287       {
288 #ifdef _GLIBCXX_DEBUG_PEDANTIC
289         return _M_guaranteed_capacity;
290 #else
291         return _Base::capacity();
292 #endif
293       }
295       using _Base::empty;
297       void
298       reserve(size_type __n)
299       {
300         bool __realloc = _M_requires_reallocation(__n);
301         _Base::reserve(__n);
302         if (__n > _M_guaranteed_capacity)
303           _M_guaranteed_capacity = __n;
304         if (__realloc)
305           this->_M_invalidate_all();
306       }
308       // element access:
309       reference
310       operator[](size_type __n)
311       {
312         __glibcxx_check_subscript(__n);
313         return _M_base()[__n];
314       }
316       const_reference
317       operator[](size_type __n) const
318       {
319         __glibcxx_check_subscript(__n);
320         return _M_base()[__n];
321       }
323       using _Base::at;
325       reference
326       front()
327       {
328         __glibcxx_check_nonempty();
329         return _Base::front();
330       }
332       const_reference
333       front() const
334       {
335         __glibcxx_check_nonempty();
336         return _Base::front();
337       }
339       reference
340       back()
341       {
342         __glibcxx_check_nonempty();
343         return _Base::back();
344       }
346       const_reference
347       back() const
348       {
349         __glibcxx_check_nonempty();
350         return _Base::back();
351       }
353       // _GLIBCXX_RESOLVE_LIB_DEFECTS
354       // DR 464. Suggestion for new member functions in standard containers.
355       using _Base::data;
357       // 23.2.4.3 modifiers:
358       void
359       push_back(const _Tp& __x)
360       {
361         bool __realloc = _M_requires_reallocation(this->size() + 1);
362         _Base::push_back(__x);
363         if (__realloc)
364           this->_M_invalidate_all();
365         _M_update_guaranteed_capacity();
366       }
368 #ifdef __GXX_EXPERIMENTAL_CXX0X__
369       template<typename _Up = _Tp>
370         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
371                                         void>::__type
372         push_back(_Tp&& __x)
373         { emplace_back(std::move(__x)); }
375       template<typename... _Args>
376         void
377         emplace_back(_Args&&... __args)
378         {
379           bool __realloc = _M_requires_reallocation(this->size() + 1);
380           _Base::emplace_back(std::forward<_Args>(__args)...);
381           if (__realloc)
382             this->_M_invalidate_all();
383           _M_update_guaranteed_capacity();
384         }
385 #endif
387       void
388       pop_back()
389       {
390         __glibcxx_check_nonempty();
391         iterator __victim = end() - 1;
392         __victim._M_invalidate();
393         _Base::pop_back();
394       }
396 #ifdef __GXX_EXPERIMENTAL_CXX0X__
397       template<typename... _Args>
398         iterator
399         emplace(iterator __position, _Args&&... __args)
400         {
401           __glibcxx_check_insert(__position);
402           bool __realloc = _M_requires_reallocation(this->size() + 1);
403           difference_type __offset = __position - begin();
404           typename _Base::iterator __res = _Base::emplace(__position.base(),
405                                             std::forward<_Args>(__args)...);
406           if (__realloc)
407             this->_M_invalidate_all();
408           else
409             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
410           _M_update_guaranteed_capacity();
411           return iterator(__res, this);
412         }
413 #endif
415       iterator
416       insert(iterator __position, const _Tp& __x)
417       {
418         __glibcxx_check_insert(__position);
419         bool __realloc = _M_requires_reallocation(this->size() + 1);
420         difference_type __offset = __position - begin();
421         typename _Base::iterator __res = _Base::insert(__position.base(),__x);
422         if (__realloc)
423           this->_M_invalidate_all();
424         else
425           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
426         _M_update_guaranteed_capacity();
427         return iterator(__res, this);
428       }
430 #ifdef __GXX_EXPERIMENTAL_CXX0X__
431       template<typename _Up = _Tp>
432         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
433                                         iterator>::__type
434         insert(iterator __position, _Tp&& __x)
435         { return emplace(__position, std::move(__x)); }
437       void
438       insert(iterator __position, initializer_list<value_type> __l)
439       { this->insert(__position, __l.begin(), __l.end()); }
440 #endif
442       void
443       insert(iterator __position, size_type __n, const _Tp& __x)
444       {
445         __glibcxx_check_insert(__position);
446         bool __realloc = _M_requires_reallocation(this->size() + __n);
447         difference_type __offset = __position - begin();
448         _Base::insert(__position.base(), __n, __x);
449         if (__realloc)
450           this->_M_invalidate_all();
451         else
452           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
453         _M_update_guaranteed_capacity();
454       }
456       template<class _InputIterator>
457         void
458         insert(iterator __position,
459                _InputIterator __first, _InputIterator __last)
460         {
461           __glibcxx_check_insert_range(__position, __first, __last);
463           /* Hard to guess if invalidation will occur, because __last
464              - __first can't be calculated in all cases, so we just
465              punt here by checking if it did occur. */
466           typename _Base::iterator __old_begin = _M_base().begin();
467           difference_type __offset = __position - begin();
468           _Base::insert(__position.base(), __gnu_debug::__base(__first),
469                                            __gnu_debug::__base(__last));
471           if (_M_base().begin() != __old_begin)
472             this->_M_invalidate_all();
473           else
474             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
475           _M_update_guaranteed_capacity();
476         }
478       iterator
479       erase(iterator __position)
480       {
481         __glibcxx_check_erase(__position);
482         difference_type __offset = __position - begin();
483         typename _Base::iterator __res = _Base::erase(__position.base());
484         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
485         return iterator(__res, this);
486       }
488       iterator
489       erase(iterator __first, iterator __last)
490       {
491         // _GLIBCXX_RESOLVE_LIB_DEFECTS
492         // 151. can't currently clear() empty container
493         __glibcxx_check_erase_range(__first, __last);
495         difference_type __offset = __first - begin();
496         typename _Base::iterator __res = _Base::erase(__first.base(),
497                                                          __last.base());
498         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
499         return iterator(__res, this);
500       }
502       void
503       swap(vector& __x)
504       {
505         _Base::swap(__x);
506         this->_M_swap(__x);
507         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
508       }
510       void
511       clear()
512       {
513         _Base::clear();
514         this->_M_invalidate_all();
515         _M_guaranteed_capacity = 0;
516       }
518       _Base&
519       _M_base() { return *this; }
521       const _Base&
522       _M_base() const { return *this; }
524     private:
525       size_type _M_guaranteed_capacity;
527       bool
528       _M_requires_reallocation(size_type __elements)
529       { return __elements > this->capacity(); }
531       void
532       _M_update_guaranteed_capacity()
533       {
534         if (this->size() > _M_guaranteed_capacity)
535           _M_guaranteed_capacity = this->size();
536       }
537     };
539   template<typename _Tp, typename _Alloc>
540     inline bool
541     operator==(const vector<_Tp, _Alloc>& __lhs,
542                const vector<_Tp, _Alloc>& __rhs)
543     { return __lhs._M_base() == __rhs._M_base(); }
545   template<typename _Tp, typename _Alloc>
546     inline bool
547     operator!=(const vector<_Tp, _Alloc>& __lhs,
548                const vector<_Tp, _Alloc>& __rhs)
549     { return __lhs._M_base() != __rhs._M_base(); }
551   template<typename _Tp, typename _Alloc>
552     inline bool
553     operator<(const vector<_Tp, _Alloc>& __lhs,
554               const vector<_Tp, _Alloc>& __rhs)
555     { return __lhs._M_base() < __rhs._M_base(); }
557   template<typename _Tp, typename _Alloc>
558     inline bool
559     operator<=(const vector<_Tp, _Alloc>& __lhs,
560                const vector<_Tp, _Alloc>& __rhs)
561     { return __lhs._M_base() <= __rhs._M_base(); }
563   template<typename _Tp, typename _Alloc>
564     inline bool
565     operator>=(const vector<_Tp, _Alloc>& __lhs,
566                const vector<_Tp, _Alloc>& __rhs)
567     { return __lhs._M_base() >= __rhs._M_base(); }
569   template<typename _Tp, typename _Alloc>
570     inline bool
571     operator>(const vector<_Tp, _Alloc>& __lhs,
572               const vector<_Tp, _Alloc>& __rhs)
573     { return __lhs._M_base() > __rhs._M_base(); }
575   template<typename _Tp, typename _Alloc>
576     inline void
577     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
578     { __lhs.swap(__rhs); }
580 } // namespace __debug
582 #ifdef __GXX_EXPERIMENTAL_CXX0X__
583   // DR 1182.
584   /// std::hash specialization for vector<bool>.
585   template<typename _Alloc>
586     struct hash<__debug::vector<bool, _Alloc>>
587     : public __hash_base<size_t, __debug::vector<bool, _Alloc>>
588     {
589       size_t
590       operator()(const __debug::vector<bool, _Alloc>& __b) const
591       { return std::hash<_GLIBCXX_STD_D::vector<bool, _Alloc>>()
592           (__b._M_base()); }
593     };
594 #endif
596 } // namespace std
598 #endif