* include/bits/stl_vector.h (vector(size_type)): Add missing allocator
[official-gcc.git] / libstdc++-v3 / include / debug / vector
blobfe65bab0c7a3aca73372fe73958ea060f3c8c6d6
1 // Debugging vector implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
4 // 2012
5 // Free Software Foundation, Inc.
6 //
7 // This file is part of the GNU ISO C++ Library.  This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
11 // any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
18 // Under Section 7 of GPL version 3, you are granted additional
19 // permissions described in the GCC Runtime Library Exception, version
20 // 3.1, as published by the Free Software Foundation.
22 // You should have received a copy of the GNU General Public License and
23 // a copy of the GCC Runtime Library Exception along with this program;
24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 // <http://www.gnu.org/licenses/>.
27 /** @file debug/vector
28  *  This file is a GNU debug extension to the Standard C++ Library.
29  */
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 _GLIBCXX_VISIBILITY(default)
41 namespace __debug
43   /// Class std::vector with safety/checking/debug instrumentation.
44   template<typename _Tp,
45            typename _Allocator = std::allocator<_Tp> >
46     class vector
47     : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
48       public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
49     {
50       typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
52       typedef typename _Base::iterator _Base_iterator;
53       typedef typename _Base::const_iterator _Base_const_iterator;
54       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
56 #ifdef __GXX_EXPERIMENTAL_CXX0X__
57       typedef __gnu_cxx::__alloc_traits<_Allocator>  _Alloc_traits;
58 #endif
60     public:
61       typedef typename _Base::reference             reference;
62       typedef typename _Base::const_reference       const_reference;
64       typedef __gnu_debug::_Safe_iterator<_Base_iterator,vector>
65       iterator;
66       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,vector>
67       const_iterator;
69       typedef typename _Base::size_type             size_type;
70       typedef typename _Base::difference_type       difference_type;
72       typedef _Tp                                   value_type;
73       typedef _Allocator                            allocator_type;
74       typedef typename _Base::pointer               pointer;
75       typedef typename _Base::const_pointer         const_pointer;
76       typedef std::reverse_iterator<iterator>       reverse_iterator;
77       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
79       // 23.2.4.1 construct/copy/destroy:
80       explicit
81       vector(const _Allocator& __a = _Allocator())
82       : _Base(__a), _M_guaranteed_capacity(0) { }
84 #ifdef __GXX_EXPERIMENTAL_CXX0X__
85       explicit
86       vector(size_type __n, const _Allocator& __a = _Allocator())
87       : _Base(__n, __a), _M_guaranteed_capacity(__n) { }
89       vector(size_type __n, const _Tp& __value,
90              const _Allocator& __a = _Allocator())
91       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
92 #else
93       explicit
94       vector(size_type __n, const _Tp& __value = _Tp(),
95              const _Allocator& __a = _Allocator())
96       : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
97 #endif
99 #ifdef __GXX_EXPERIMENTAL_CXX0X__
100       template<class _InputIterator,
101                typename = std::_RequireInputIter<_InputIterator>>
102 #else
103       template<class _InputIterator>
104 #endif
105         vector(_InputIterator __first, _InputIterator __last,
106                const _Allocator& __a = _Allocator())
107         : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
108                                                                      __last)),
109                 __gnu_debug::__base(__last), __a),
110           _M_guaranteed_capacity(0)
111         { _M_update_guaranteed_capacity(); }
113       vector(const vector& __x)
114       : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
116       /// Construction from a release-mode vector
117       vector(const _Base& __x)
118       : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
120 #ifdef __GXX_EXPERIMENTAL_CXX0X__
121       vector(vector&& __x) noexcept
122       : _Base(std::move(__x)),
123         _M_guaranteed_capacity(this->size())
124       {
125         this->_M_swap(__x);
126         __x._M_guaranteed_capacity = 0;
127       }
129       vector(const vector& __x, const allocator_type& __a)
130       : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { }
132       vector(vector&& __x, const allocator_type& __a)
133       : _Base(std::move(__x), __a),
134         _M_guaranteed_capacity(this->size())
135       {
136         __x._M_invalidate_all();
137         __x._M_guaranteed_capacity = 0;
138       }
140       vector(initializer_list<value_type> __l,
141              const allocator_type& __a = allocator_type())
142       : _Base(__l, __a),
143         _M_guaranteed_capacity(__l.size()) { }
144 #endif
146       ~vector() _GLIBCXX_NOEXCEPT { }
148       vector&
149       operator=(const vector& __x)
150       {
151         static_cast<_Base&>(*this) = __x;
152         this->_M_invalidate_all();
153         _M_update_guaranteed_capacity();
154         return *this;
155       }
157 #ifdef __GXX_EXPERIMENTAL_CXX0X__
158       vector&
159       operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
160       {
161         __glibcxx_check_self_move_assign(__x);
162         _Base::operator=(std::move(__x));
163         this->_M_invalidate_all();
164         _M_update_guaranteed_capacity();
165         __x._M_invalidate_all();
166         __x._M_guaranteed_capacity = 0;
167         return *this;
168       }
170       vector&
171       operator=(initializer_list<value_type> __l)
172       {
173         static_cast<_Base&>(*this) = __l;
174         this->_M_invalidate_all();
175         _M_update_guaranteed_capacity();
176         return *this;
177       }
178 #endif
180 #ifdef __GXX_EXPERIMENTAL_CXX0X__
181       template<typename _InputIterator,
182                typename = std::_RequireInputIter<_InputIterator>>
183 #else
184       template<typename _InputIterator>
185 #endif
186         void
187         assign(_InputIterator __first, _InputIterator __last)
188         {
189           __glibcxx_check_valid_range(__first, __last);
190           _Base::assign(__gnu_debug::__base(__first),
191                         __gnu_debug::__base(__last));
192           this->_M_invalidate_all();
193           _M_update_guaranteed_capacity();
194         }
196       void
197       assign(size_type __n, const _Tp& __u)
198       {
199         _Base::assign(__n, __u);
200         this->_M_invalidate_all();
201         _M_update_guaranteed_capacity();
202       }
204 #ifdef __GXX_EXPERIMENTAL_CXX0X__
205       void
206       assign(initializer_list<value_type> __l)
207       {
208         _Base::assign(__l);
209         this->_M_invalidate_all();
210         _M_update_guaranteed_capacity();
211       }
212 #endif
214       using _Base::get_allocator;
216       // iterators:
217       iterator
218       begin() _GLIBCXX_NOEXCEPT
219       { return iterator(_Base::begin(), this); }
221       const_iterator
222       begin() const _GLIBCXX_NOEXCEPT
223       { return const_iterator(_Base::begin(), this); }
225       iterator
226       end() _GLIBCXX_NOEXCEPT
227       { return iterator(_Base::end(), this); }
229       const_iterator
230       end() const _GLIBCXX_NOEXCEPT
231       { return const_iterator(_Base::end(), this); }
233       reverse_iterator
234       rbegin() _GLIBCXX_NOEXCEPT
235       { return reverse_iterator(end()); }
237       const_reverse_iterator
238       rbegin() const _GLIBCXX_NOEXCEPT
239       { return const_reverse_iterator(end()); }
241       reverse_iterator
242       rend() _GLIBCXX_NOEXCEPT
243       { return reverse_iterator(begin()); }
245       const_reverse_iterator
246       rend() const _GLIBCXX_NOEXCEPT
247       { return const_reverse_iterator(begin()); }
249 #ifdef __GXX_EXPERIMENTAL_CXX0X__
250       const_iterator
251       cbegin() const noexcept
252       { return const_iterator(_Base::begin(), this); }
254       const_iterator
255       cend() const noexcept
256       { return const_iterator(_Base::end(), this); }
258       const_reverse_iterator
259       crbegin() const noexcept
260       { return const_reverse_iterator(end()); }
262       const_reverse_iterator
263       crend() const noexcept
264       { return const_reverse_iterator(begin()); }
265 #endif
267       // 23.2.4.2 capacity:
268       using _Base::size;
269       using _Base::max_size;
271 #ifdef __GXX_EXPERIMENTAL_CXX0X__
272       void
273       resize(size_type __sz)
274       {
275         bool __realloc = _M_requires_reallocation(__sz);
276         if (__sz < this->size())
277           this->_M_invalidate_after_nth(__sz);
278         _Base::resize(__sz);
279         if (__realloc)
280           this->_M_invalidate_all();
281         _M_update_guaranteed_capacity();
282       }
284       void
285       resize(size_type __sz, const _Tp& __c)
286       {
287         bool __realloc = _M_requires_reallocation(__sz);
288         if (__sz < this->size())
289           this->_M_invalidate_after_nth(__sz);
290         _Base::resize(__sz, __c);
291         if (__realloc)
292           this->_M_invalidate_all();
293         _M_update_guaranteed_capacity();
294       }
295 #else
296       void
297       resize(size_type __sz, _Tp __c = _Tp())
298       {
299         bool __realloc = _M_requires_reallocation(__sz);
300         if (__sz < this->size())
301           this->_M_invalidate_after_nth(__sz);
302         _Base::resize(__sz, __c);
303         if (__realloc)
304           this->_M_invalidate_all();
305         _M_update_guaranteed_capacity();
306       }
307 #endif
309 #ifdef __GXX_EXPERIMENTAL_CXX0X__
310       void
311       shrink_to_fit()
312       {
313         if (_Base::_M_shrink_to_fit())
314           {
315             _M_guaranteed_capacity = _Base::capacity();
316             this->_M_invalidate_all();
317           }
318       }
319 #endif
321       size_type
322       capacity() const _GLIBCXX_NOEXCEPT
323       {
324 #ifdef _GLIBCXX_DEBUG_PEDANTIC
325         return _M_guaranteed_capacity;
326 #else
327         return _Base::capacity();
328 #endif
329       }
331       using _Base::empty;
333       void
334       reserve(size_type __n)
335       {
336         bool __realloc = _M_requires_reallocation(__n);
337         _Base::reserve(__n);
338         if (__n > _M_guaranteed_capacity)
339           _M_guaranteed_capacity = __n;
340         if (__realloc)
341           this->_M_invalidate_all();
342       }
344       // element access:
345       reference
346       operator[](size_type __n)
347       {
348         __glibcxx_check_subscript(__n);
349         return _M_base()[__n];
350       }
352       const_reference
353       operator[](size_type __n) const
354       {
355         __glibcxx_check_subscript(__n);
356         return _M_base()[__n];
357       }
359       using _Base::at;
361       reference
362       front()
363       {
364         __glibcxx_check_nonempty();
365         return _Base::front();
366       }
368       const_reference
369       front() const
370       {
371         __glibcxx_check_nonempty();
372         return _Base::front();
373       }
375       reference
376       back()
377       {
378         __glibcxx_check_nonempty();
379         return _Base::back();
380       }
382       const_reference
383       back() const
384       {
385         __glibcxx_check_nonempty();
386         return _Base::back();
387       }
389       // _GLIBCXX_RESOLVE_LIB_DEFECTS
390       // DR 464. Suggestion for new member functions in standard containers.
391       using _Base::data;
393       // 23.2.4.3 modifiers:
394       void
395       push_back(const _Tp& __x)
396       {
397         bool __realloc = _M_requires_reallocation(this->size() + 1);
398         _Base::push_back(__x);
399         if (__realloc)
400           this->_M_invalidate_all();
401         _M_update_guaranteed_capacity();
402       }
404 #ifdef __GXX_EXPERIMENTAL_CXX0X__
405       template<typename _Up = _Tp>
406         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
407                                         void>::__type
408         push_back(_Tp&& __x)
409         { emplace_back(std::move(__x)); }
411       template<typename... _Args>
412         void
413         emplace_back(_Args&&... __args)
414         {
415           bool __realloc = _M_requires_reallocation(this->size() + 1);
416           _Base::emplace_back(std::forward<_Args>(__args)...);
417           if (__realloc)
418             this->_M_invalidate_all();
419           _M_update_guaranteed_capacity();
420         }
421 #endif
423       void
424       pop_back()
425       {
426         __glibcxx_check_nonempty();
427         this->_M_invalidate_if(_Equal(--_Base::end()));
428         _Base::pop_back();
429       }
431 #ifdef __GXX_EXPERIMENTAL_CXX0X__
432       template<typename... _Args>
433         iterator
434         emplace(iterator __position, _Args&&... __args)
435         {
436           __glibcxx_check_insert(__position);
437           bool __realloc = _M_requires_reallocation(this->size() + 1);
438           difference_type __offset = __position.base() - _Base::begin();
439           _Base_iterator __res = _Base::emplace(__position.base(),
440                                                 std::forward<_Args>(__args)...);
441           if (__realloc)
442             this->_M_invalidate_all();
443           else
444             this->_M_invalidate_after_nth(__offset);
445           _M_update_guaranteed_capacity();
446           return iterator(__res, this);
447         }
448 #endif
450       iterator
451       insert(iterator __position, const _Tp& __x)
452       {
453         __glibcxx_check_insert(__position);
454         bool __realloc = _M_requires_reallocation(this->size() + 1);
455         difference_type __offset = __position.base() - _Base::begin();
456         _Base_iterator __res = _Base::insert(__position.base(), __x);
457         if (__realloc)
458           this->_M_invalidate_all();
459         else
460           this->_M_invalidate_after_nth(__offset);
461         _M_update_guaranteed_capacity();
462         return iterator(__res, this);
463       }
465 #ifdef __GXX_EXPERIMENTAL_CXX0X__
466       template<typename _Up = _Tp>
467         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
468                                         iterator>::__type
469         insert(iterator __position, _Tp&& __x)
470         { return emplace(__position, std::move(__x)); }
472       void
473       insert(iterator __position, initializer_list<value_type> __l)
474       { this->insert(__position, __l.begin(), __l.end()); }
475 #endif
477       void
478       insert(iterator __position, size_type __n, const _Tp& __x)
479       {
480         __glibcxx_check_insert(__position);
481         bool __realloc = _M_requires_reallocation(this->size() + __n);
482         difference_type __offset = __position.base() - _Base::begin();
483         _Base::insert(__position.base(), __n, __x);
484         if (__realloc)
485           this->_M_invalidate_all();
486         else
487           this->_M_invalidate_after_nth(__offset);
488         _M_update_guaranteed_capacity();
489       }
491 #ifdef __GXX_EXPERIMENTAL_CXX0X__
492       template<class _InputIterator,
493                typename = std::_RequireInputIter<_InputIterator>>
494 #else
495       template<class _InputIterator>
496 #endif
497         void
498         insert(iterator __position,
499                _InputIterator __first, _InputIterator __last)
500         {
501           __glibcxx_check_insert_range(__position, __first, __last);
503           /* Hard to guess if invalidation will occur, because __last
504              - __first can't be calculated in all cases, so we just
505              punt here by checking if it did occur. */
506           _Base_iterator __old_begin = _M_base().begin();
507           difference_type __offset = __position.base() - _Base::begin();
508           _Base::insert(__position.base(), __gnu_debug::__base(__first),
509                                            __gnu_debug::__base(__last));
511           if (_M_base().begin() != __old_begin)
512             this->_M_invalidate_all();
513           else
514             this->_M_invalidate_after_nth(__offset);
515           _M_update_guaranteed_capacity();
516         }
518       iterator
519       erase(iterator __position)
520       {
521         __glibcxx_check_erase(__position);
522         difference_type __offset = __position.base() - _Base::begin();
523         _Base_iterator __res = _Base::erase(__position.base());
524         this->_M_invalidate_after_nth(__offset);
525         return iterator(__res, this);
526       }
528       iterator
529       erase(iterator __first, iterator __last)
530       {
531         // _GLIBCXX_RESOLVE_LIB_DEFECTS
532         // 151. can't currently clear() empty container
533         __glibcxx_check_erase_range(__first, __last);
535         if (__first.base() != __last.base())
536           {
537             difference_type __offset = __first.base() - _Base::begin();
538             _Base_iterator __res = _Base::erase(__first.base(),
539                                                 __last.base());
540             this->_M_invalidate_after_nth(__offset);
541             return iterator(__res, this);
542           }
543         else
544           return __first;
545       }
547       void
548       swap(vector& __x)
549 #ifdef __GXX_EXPERIMENTAL_CXX0X__
550                         noexcept(_Alloc_traits::_S_nothrow_swap())
551 #endif
552       {
553 #ifdef __GXX_EXPERIMENTAL_CXX0X__
554         if (!_Alloc_traits::_S_propagate_on_swap())
555           __glibcxx_check_equal_allocs(__x);
556 #endif
557         _Base::swap(__x);
558         this->_M_swap(__x);
559         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
560       }
562       void
563       clear() _GLIBCXX_NOEXCEPT
564       {
565         _Base::clear();
566         this->_M_invalidate_all();
567         _M_guaranteed_capacity = 0;
568       }
570       _Base&
571       _M_base() _GLIBCXX_NOEXCEPT { return *this; }
573       const _Base&
574       _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
576     private:
577       size_type _M_guaranteed_capacity;
579       bool
580       _M_requires_reallocation(size_type __elements)
581       { return __elements > this->capacity(); }
583       void
584       _M_update_guaranteed_capacity()
585       {
586         if (this->size() > _M_guaranteed_capacity)
587           _M_guaranteed_capacity = this->size();
588       }
590       void
591       _M_invalidate_after_nth(difference_type __n)
592       {
593         typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
594         this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
595       }
596     };
598   template<typename _Tp, typename _Alloc>
599     inline bool
600     operator==(const vector<_Tp, _Alloc>& __lhs,
601                const vector<_Tp, _Alloc>& __rhs)
602     { return __lhs._M_base() == __rhs._M_base(); }
604   template<typename _Tp, typename _Alloc>
605     inline bool
606     operator!=(const vector<_Tp, _Alloc>& __lhs,
607                const vector<_Tp, _Alloc>& __rhs)
608     { return __lhs._M_base() != __rhs._M_base(); }
610   template<typename _Tp, typename _Alloc>
611     inline bool
612     operator<(const vector<_Tp, _Alloc>& __lhs,
613               const vector<_Tp, _Alloc>& __rhs)
614     { return __lhs._M_base() < __rhs._M_base(); }
616   template<typename _Tp, typename _Alloc>
617     inline bool
618     operator<=(const vector<_Tp, _Alloc>& __lhs,
619                const vector<_Tp, _Alloc>& __rhs)
620     { return __lhs._M_base() <= __rhs._M_base(); }
622   template<typename _Tp, typename _Alloc>
623     inline bool
624     operator>=(const vector<_Tp, _Alloc>& __lhs,
625                const vector<_Tp, _Alloc>& __rhs)
626     { return __lhs._M_base() >= __rhs._M_base(); }
628   template<typename _Tp, typename _Alloc>
629     inline bool
630     operator>(const vector<_Tp, _Alloc>& __lhs,
631               const vector<_Tp, _Alloc>& __rhs)
632     { return __lhs._M_base() > __rhs._M_base(); }
634   template<typename _Tp, typename _Alloc>
635     inline void
636     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
637     { __lhs.swap(__rhs); }
639 } // namespace __debug
641 #ifdef __GXX_EXPERIMENTAL_CXX0X__
642   // DR 1182.
643   /// std::hash specialization for vector<bool>.
644   template<typename _Alloc>
645     struct hash<__debug::vector<bool, _Alloc>>
646     : public __hash_base<size_t, __debug::vector<bool, _Alloc>>
647     {
648       size_t
649       operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
650       { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>()
651           (__b._M_base()); }
652     };
653 #endif
655 } // namespace std
657 #endif