libstdc++
debug/vector
Go to the documentation of this file.
1 // Debugging vector implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file debug/vector
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_VECTOR
30 #define _GLIBCXX_DEBUG_VECTOR 1
31 
32 #include <vector>
33 #include <utility>
34 #include <debug/safe_sequence.h>
35 #include <debug/safe_iterator.h>
36 
37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39 namespace __debug
40 {
41  /// Class std::vector with safety/checking/debug instrumentation.
42  template<typename _Tp,
43  typename _Allocator = std::allocator<_Tp> >
44  class vector
45  : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
46  public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
47  {
48  typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
49 
50  typedef typename _Base::iterator _Base_iterator;
53 
54 #if __cplusplus >= 201103L
56 #endif
57 
58  public:
59  typedef typename _Base::reference reference;
60  typedef typename _Base::const_reference const_reference;
61 
63  iterator;
66 
67  typedef typename _Base::size_type size_type;
68  typedef typename _Base::difference_type difference_type;
69 
70  typedef _Tp value_type;
71  typedef _Allocator allocator_type;
72  typedef typename _Base::pointer pointer;
73  typedef typename _Base::const_pointer const_pointer;
76 
77  // 23.2.4.1 construct/copy/destroy:
78  explicit
79  vector(const _Allocator& __a = _Allocator()) _GLIBCXX_NOEXCEPT
80  : _Base(__a), _M_guaranteed_capacity(0) { }
81 
82 #if __cplusplus >= 201103L
83  explicit
84  vector(size_type __n, const _Allocator& __a = _Allocator())
85  : _Base(__n, __a), _M_guaranteed_capacity(__n) { }
86 
87  vector(size_type __n, const _Tp& __value,
88  const _Allocator& __a = _Allocator())
89  : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
90 #else
91  explicit
92  vector(size_type __n, const _Tp& __value = _Tp(),
93  const _Allocator& __a = _Allocator())
94  : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
95 #endif
96 
97 #if __cplusplus >= 201103L
98  template<class _InputIterator,
99  typename = std::_RequireInputIter<_InputIterator>>
100 #else
101  template<class _InputIterator>
102 #endif
103  vector(_InputIterator __first, _InputIterator __last,
104  const _Allocator& __a = _Allocator())
105  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
106  __last)),
107  __gnu_debug::__base(__last), __a),
108  _M_guaranteed_capacity(0)
109  { _M_update_guaranteed_capacity(); }
110 
111  vector(const vector& __x)
112  : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
113 
114  /// Construction from a release-mode vector
115  vector(const _Base& __x)
116  : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
117 
118 #if __cplusplus >= 201103L
119  vector(vector&& __x) noexcept
120  : _Base(std::move(__x)),
121  _M_guaranteed_capacity(this->size())
122  {
123  this->_M_swap(__x);
124  __x._M_guaranteed_capacity = 0;
125  }
126 
127  vector(const vector& __x, const allocator_type& __a)
128  : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { }
129 
130  vector(vector&& __x, const allocator_type& __a)
131  : _Base(std::move(__x), __a),
132  _M_guaranteed_capacity(this->size())
133  {
134  __x._M_invalidate_all();
135  __x._M_guaranteed_capacity = 0;
136  }
137 
138  vector(initializer_list<value_type> __l,
139  const allocator_type& __a = allocator_type())
140  : _Base(__l, __a),
141  _M_guaranteed_capacity(__l.size()) { }
142 #endif
143 
144  ~vector() _GLIBCXX_NOEXCEPT { }
145 
146  vector&
147  operator=(const vector& __x)
148  {
149  static_cast<_Base&>(*this) = __x;
150  this->_M_invalidate_all();
151  _M_update_guaranteed_capacity();
152  return *this;
153  }
154 
155 #if __cplusplus >= 201103L
156  vector&
157  operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
158  {
159  __glibcxx_check_self_move_assign(__x);
160  _Base::operator=(std::move(__x));
161  this->_M_invalidate_all();
162  _M_update_guaranteed_capacity();
163  __x._M_invalidate_all();
164  __x._M_guaranteed_capacity = 0;
165  return *this;
166  }
167 
168  vector&
169  operator=(initializer_list<value_type> __l)
170  {
171  static_cast<_Base&>(*this) = __l;
172  this->_M_invalidate_all();
173  _M_update_guaranteed_capacity();
174  return *this;
175  }
176 #endif
177 
178 #if __cplusplus >= 201103L
179  template<typename _InputIterator,
180  typename = std::_RequireInputIter<_InputIterator>>
181 #else
182  template<typename _InputIterator>
183 #endif
184  void
185  assign(_InputIterator __first, _InputIterator __last)
186  {
187  __glibcxx_check_valid_range(__first, __last);
188  _Base::assign(__gnu_debug::__base(__first),
189  __gnu_debug::__base(__last));
190  this->_M_invalidate_all();
191  _M_update_guaranteed_capacity();
192  }
193 
194  void
195  assign(size_type __n, const _Tp& __u)
196  {
197  _Base::assign(__n, __u);
198  this->_M_invalidate_all();
199  _M_update_guaranteed_capacity();
200  }
201 
202 #if __cplusplus >= 201103L
203  void
204  assign(initializer_list<value_type> __l)
205  {
206  _Base::assign(__l);
207  this->_M_invalidate_all();
208  _M_update_guaranteed_capacity();
209  }
210 #endif
211 
212  using _Base::get_allocator;
213 
214  // iterators:
215  iterator
216  begin() _GLIBCXX_NOEXCEPT
217  { return iterator(_Base::begin(), this); }
218 
219  const_iterator
220  begin() const _GLIBCXX_NOEXCEPT
221  { return const_iterator(_Base::begin(), this); }
222 
223  iterator
224  end() _GLIBCXX_NOEXCEPT
225  { return iterator(_Base::end(), this); }
226 
227  const_iterator
228  end() const _GLIBCXX_NOEXCEPT
229  { return const_iterator(_Base::end(), this); }
230 
231  reverse_iterator
232  rbegin() _GLIBCXX_NOEXCEPT
233  { return reverse_iterator(end()); }
234 
235  const_reverse_iterator
236  rbegin() const _GLIBCXX_NOEXCEPT
237  { return const_reverse_iterator(end()); }
238 
239  reverse_iterator
240  rend() _GLIBCXX_NOEXCEPT
241  { return reverse_iterator(begin()); }
242 
243  const_reverse_iterator
244  rend() const _GLIBCXX_NOEXCEPT
245  { return const_reverse_iterator(begin()); }
246 
247 #if __cplusplus >= 201103L
248  const_iterator
249  cbegin() const noexcept
250  { return const_iterator(_Base::begin(), this); }
251 
252  const_iterator
253  cend() const noexcept
254  { return const_iterator(_Base::end(), this); }
255 
256  const_reverse_iterator
257  crbegin() const noexcept
258  { return const_reverse_iterator(end()); }
259 
260  const_reverse_iterator
261  crend() const noexcept
262  { return const_reverse_iterator(begin()); }
263 #endif
264 
265  // 23.2.4.2 capacity:
266  using _Base::size;
267  using _Base::max_size;
268 
269 #if __cplusplus >= 201103L
270  void
271  resize(size_type __sz)
272  {
273  bool __realloc = _M_requires_reallocation(__sz);
274  if (__sz < this->size())
275  this->_M_invalidate_after_nth(__sz);
276  _Base::resize(__sz);
277  if (__realloc)
278  this->_M_invalidate_all();
279  _M_update_guaranteed_capacity();
280  }
281 
282  void
283  resize(size_type __sz, const _Tp& __c)
284  {
285  bool __realloc = _M_requires_reallocation(__sz);
286  if (__sz < this->size())
287  this->_M_invalidate_after_nth(__sz);
288  _Base::resize(__sz, __c);
289  if (__realloc)
290  this->_M_invalidate_all();
291  _M_update_guaranteed_capacity();
292  }
293 #else
294  void
295  resize(size_type __sz, _Tp __c = _Tp())
296  {
297  bool __realloc = _M_requires_reallocation(__sz);
298  if (__sz < this->size())
299  this->_M_invalidate_after_nth(__sz);
300  _Base::resize(__sz, __c);
301  if (__realloc)
302  this->_M_invalidate_all();
303  _M_update_guaranteed_capacity();
304  }
305 #endif
306 
307 #if __cplusplus >= 201103L
308  void
309  shrink_to_fit()
310  {
311  if (_Base::_M_shrink_to_fit())
312  {
313  _M_guaranteed_capacity = _Base::capacity();
314  this->_M_invalidate_all();
315  }
316  }
317 #endif
318 
319  size_type
320  capacity() const _GLIBCXX_NOEXCEPT
321  {
322 #ifdef _GLIBCXX_DEBUG_PEDANTIC
323  return _M_guaranteed_capacity;
324 #else
325  return _Base::capacity();
326 #endif
327  }
328 
329  using _Base::empty;
330 
331  void
332  reserve(size_type __n)
333  {
334  bool __realloc = _M_requires_reallocation(__n);
335  _Base::reserve(__n);
336  if (__n > _M_guaranteed_capacity)
337  _M_guaranteed_capacity = __n;
338  if (__realloc)
339  this->_M_invalidate_all();
340  }
341 
342  // element access:
343  reference
344  operator[](size_type __n) _GLIBCXX_NOEXCEPT
345  {
346  __glibcxx_check_subscript(__n);
347  return _M_base()[__n];
348  }
349 
350  const_reference
351  operator[](size_type __n) const _GLIBCXX_NOEXCEPT
352  {
353  __glibcxx_check_subscript(__n);
354  return _M_base()[__n];
355  }
356 
357  using _Base::at;
358 
359  reference
360  front() _GLIBCXX_NOEXCEPT
361  {
362  __glibcxx_check_nonempty();
363  return _Base::front();
364  }
365 
366  const_reference
367  front() const _GLIBCXX_NOEXCEPT
368  {
369  __glibcxx_check_nonempty();
370  return _Base::front();
371  }
372 
373  reference
374  back() _GLIBCXX_NOEXCEPT
375  {
376  __glibcxx_check_nonempty();
377  return _Base::back();
378  }
379 
380  const_reference
381  back() const _GLIBCXX_NOEXCEPT
382  {
383  __glibcxx_check_nonempty();
384  return _Base::back();
385  }
386 
387  // _GLIBCXX_RESOLVE_LIB_DEFECTS
388  // DR 464. Suggestion for new member functions in standard containers.
389  using _Base::data;
390 
391  // 23.2.4.3 modifiers:
392  void
393  push_back(const _Tp& __x)
394  {
395  bool __realloc = _M_requires_reallocation(this->size() + 1);
396  _Base::push_back(__x);
397  if (__realloc)
398  this->_M_invalidate_all();
399  _M_update_guaranteed_capacity();
400  }
401 
402 #if __cplusplus >= 201103L
403  template<typename _Up = _Tp>
404  typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
405  void>::__type
406  push_back(_Tp&& __x)
407  { emplace_back(std::move(__x)); }
408 
409  template<typename... _Args>
410  void
411  emplace_back(_Args&&... __args)
412  {
413  bool __realloc = _M_requires_reallocation(this->size() + 1);
414  _Base::emplace_back(std::forward<_Args>(__args)...);
415  if (__realloc)
416  this->_M_invalidate_all();
417  _M_update_guaranteed_capacity();
418  }
419 #endif
420 
421  void
422  pop_back() _GLIBCXX_NOEXCEPT
423  {
424  __glibcxx_check_nonempty();
425  this->_M_invalidate_if(_Equal(--_Base::end()));
426  _Base::pop_back();
427  }
428 
429 #if __cplusplus >= 201103L
430  template<typename... _Args>
431  iterator
432  emplace(const_iterator __position, _Args&&... __args)
433  {
434  __glibcxx_check_insert(__position);
435  bool __realloc = _M_requires_reallocation(this->size() + 1);
436  difference_type __offset = __position.base() - _Base::begin();
437  _Base_iterator __res = _Base::emplace(__position.base(),
438  std::forward<_Args>(__args)...);
439  if (__realloc)
440  this->_M_invalidate_all();
441  else
442  this->_M_invalidate_after_nth(__offset);
443  _M_update_guaranteed_capacity();
444  return iterator(__res, this);
445  }
446 #endif
447 
448  iterator
449 #if __cplusplus >= 201103L
450  insert(const_iterator __position, const _Tp& __x)
451 #else
452  insert(iterator __position, const _Tp& __x)
453 #endif
454  {
455  __glibcxx_check_insert(__position);
456  bool __realloc = _M_requires_reallocation(this->size() + 1);
457  difference_type __offset = __position.base() - _Base::begin();
458  _Base_iterator __res = _Base::insert(__position.base(), __x);
459  if (__realloc)
460  this->_M_invalidate_all();
461  else
462  this->_M_invalidate_after_nth(__offset);
463  _M_update_guaranteed_capacity();
464  return iterator(__res, this);
465  }
466 
467 #if __cplusplus >= 201103L
468  template<typename _Up = _Tp>
469  typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
470  iterator>::__type
471  insert(const_iterator __position, _Tp&& __x)
472  { return emplace(__position, std::move(__x)); }
473 
474  iterator
475  insert(const_iterator __position, initializer_list<value_type> __l)
476  { return this->insert(__position, __l.begin(), __l.end()); }
477 #endif
478 
479 #if __cplusplus >= 201103L
480  iterator
481  insert(const_iterator __position, size_type __n, const _Tp& __x)
482  {
483  __glibcxx_check_insert(__position);
484  bool __realloc = _M_requires_reallocation(this->size() + __n);
485  difference_type __offset = __position.base() - _Base::cbegin();
486  _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
487  if (__realloc)
488  this->_M_invalidate_all();
489  else
490  this->_M_invalidate_after_nth(__offset);
491  _M_update_guaranteed_capacity();
492  return iterator(__res, this);
493  }
494 #else
495  void
496  insert(iterator __position, size_type __n, const _Tp& __x)
497  {
498  __glibcxx_check_insert(__position);
499  bool __realloc = _M_requires_reallocation(this->size() + __n);
500  difference_type __offset = __position.base() - _Base::begin();
501  _Base::insert(__position.base(), __n, __x);
502  if (__realloc)
503  this->_M_invalidate_all();
504  else
505  this->_M_invalidate_after_nth(__offset);
506  _M_update_guaranteed_capacity();
507  }
508 #endif
509 
510 #if __cplusplus >= 201103L
511  template<class _InputIterator,
512  typename = std::_RequireInputIter<_InputIterator>>
513  iterator
514  insert(const_iterator __position,
515  _InputIterator __first, _InputIterator __last)
516  {
517  __glibcxx_check_insert_range(__position, __first, __last);
518 
519  /* Hard to guess if invalidation will occur, because __last
520  - __first can't be calculated in all cases, so we just
521  punt here by checking if it did occur. */
522  _Base_iterator __old_begin = _M_base().begin();
523  difference_type __offset = __position.base() - _Base::cbegin();
524  _Base_iterator __res = _Base::insert(__position.base(),
525  __gnu_debug::__base(__first),
526  __gnu_debug::__base(__last));
527 
528  if (_M_base().begin() != __old_begin)
529  this->_M_invalidate_all();
530  else
531  this->_M_invalidate_after_nth(__offset);
532  _M_update_guaranteed_capacity();
533  return iterator(__res, this);
534  }
535 #else
536  template<class _InputIterator>
537  void
538  insert(iterator __position,
539  _InputIterator __first, _InputIterator __last)
540  {
541  __glibcxx_check_insert_range(__position, __first, __last);
542 
543  /* Hard to guess if invalidation will occur, because __last
544  - __first can't be calculated in all cases, so we just
545  punt here by checking if it did occur. */
546  _Base_iterator __old_begin = _M_base().begin();
547  difference_type __offset = __position.base() - _Base::begin();
548  _Base::insert(__position.base(), __gnu_debug::__base(__first),
549  __gnu_debug::__base(__last));
550 
551  if (_M_base().begin() != __old_begin)
552  this->_M_invalidate_all();
553  else
554  this->_M_invalidate_after_nth(__offset);
555  _M_update_guaranteed_capacity();
556  }
557 #endif
558 
559  iterator
560 #if __cplusplus >= 201103L
561  erase(const_iterator __position)
562 #else
563  erase(iterator __position)
564 #endif
565  {
566  __glibcxx_check_erase(__position);
567  difference_type __offset = __position.base() - _Base::begin();
568  _Base_iterator __res = _Base::erase(__position.base());
569  this->_M_invalidate_after_nth(__offset);
570  return iterator(__res, this);
571  }
572 
573  iterator
574 #if __cplusplus >= 201103L
575  erase(const_iterator __first, const_iterator __last)
576 #else
577  erase(iterator __first, iterator __last)
578 #endif
579  {
580  // _GLIBCXX_RESOLVE_LIB_DEFECTS
581  // 151. can't currently clear() empty container
582  __glibcxx_check_erase_range(__first, __last);
583 
584  if (__first.base() != __last.base())
585  {
586  difference_type __offset = __first.base() - _Base::begin();
587  _Base_iterator __res = _Base::erase(__first.base(),
588  __last.base());
589  this->_M_invalidate_after_nth(__offset);
590  return iterator(__res, this);
591  }
592  else
593 #if __cplusplus >= 201103L
594  return iterator(__first.base()._M_const_cast(), this);
595 #else
596  return __first;
597 #endif
598  }
599 
600  void
601  swap(vector& __x)
602 #if __cplusplus >= 201103L
603  noexcept(_Alloc_traits::_S_nothrow_swap())
604 #endif
605  {
606 #if __cplusplus >= 201103L
607  if (!_Alloc_traits::_S_propagate_on_swap())
608  __glibcxx_check_equal_allocs(__x);
609 #endif
610  _Base::swap(__x);
611  this->_M_swap(__x);
612  std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
613  }
614 
615  void
616  clear() _GLIBCXX_NOEXCEPT
617  {
618  _Base::clear();
619  this->_M_invalidate_all();
620  _M_guaranteed_capacity = 0;
621  }
622 
623  _Base&
624  _M_base() _GLIBCXX_NOEXCEPT { return *this; }
625 
626  const _Base&
627  _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
628 
629  private:
630  size_type _M_guaranteed_capacity;
631 
632  bool
633  _M_requires_reallocation(size_type __elements) _GLIBCXX_NOEXCEPT
634  { return __elements > this->capacity(); }
635 
636  void
637  _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
638  {
639  if (this->size() > _M_guaranteed_capacity)
640  _M_guaranteed_capacity = this->size();
641  }
642 
643  void
644  _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
645  {
647  this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
648  }
649  };
650 
651  template<typename _Tp, typename _Alloc>
652  inline bool
653  operator==(const vector<_Tp, _Alloc>& __lhs,
654  const vector<_Tp, _Alloc>& __rhs)
655  { return __lhs._M_base() == __rhs._M_base(); }
656 
657  template<typename _Tp, typename _Alloc>
658  inline bool
659  operator!=(const vector<_Tp, _Alloc>& __lhs,
660  const vector<_Tp, _Alloc>& __rhs)
661  { return __lhs._M_base() != __rhs._M_base(); }
662 
663  template<typename _Tp, typename _Alloc>
664  inline bool
665  operator<(const vector<_Tp, _Alloc>& __lhs,
666  const vector<_Tp, _Alloc>& __rhs)
667  { return __lhs._M_base() < __rhs._M_base(); }
668 
669  template<typename _Tp, typename _Alloc>
670  inline bool
671  operator<=(const vector<_Tp, _Alloc>& __lhs,
672  const vector<_Tp, _Alloc>& __rhs)
673  { return __lhs._M_base() <= __rhs._M_base(); }
674 
675  template<typename _Tp, typename _Alloc>
676  inline bool
677  operator>=(const vector<_Tp, _Alloc>& __lhs,
678  const vector<_Tp, _Alloc>& __rhs)
679  { return __lhs._M_base() >= __rhs._M_base(); }
680 
681  template<typename _Tp, typename _Alloc>
682  inline bool
683  operator>(const vector<_Tp, _Alloc>& __lhs,
684  const vector<_Tp, _Alloc>& __rhs)
685  { return __lhs._M_base() > __rhs._M_base(); }
686 
687  template<typename _Tp, typename _Alloc>
688  inline void
689  swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
690  { __lhs.swap(__rhs); }
691 
692 } // namespace __debug
693 
694 #if __cplusplus >= 201103L
695  // DR 1182.
696  /// std::hash specialization for vector<bool>.
697  template<typename _Alloc>
698  struct hash<__debug::vector<bool, _Alloc>>
699  : public __hash_base<size_t, __debug::vector<bool, _Alloc>>
700  {
701  size_t
702  operator()(const __debug::vector<bool, _Alloc>& __b) const noexcept
704  (__b._M_base()); }
705  };
706 #endif
707 
708 } // namespace std
709 
710 #endif
#define __glibcxx_check_insert_range(_Position, _First, _Last)
Definition: macros.h:106
#define __glibcxx_check_insert(_Position)
Definition: macros.h:73
Uniform interface to C++98 and C++0x allocators.
Class std::vector with safety/checking/debug instrumentation.
Definition: debug/vector:44
constexpr size_t size() const noexcept
Returns the total number of bits.
Definition: bitset:1293
vector(const _Base &__x)
Construction from a release-mode vector.
Definition: debug/vector:115
#define __glibcxx_check_erase(_Position)
Definition: macros.h:141
The standard allocator, as per [20.4].
Definition: allocator.h:92
void swap(function< _Res(_Args...)> &__x, function< _Res(_Args...)> &__y)
Swap the targets of two polymorphic function object wrappers.
Definition: functional:2534
Base class for constructing a safe sequence type that tracks iterators that reference it...
Definition: formatter.h:52
_Siter_base< _Iterator >::iterator_type __base(_Iterator __it)
Definition: functions.h:558
Primary class template hash.
Definition: system_error:115
Safe iterator wrapper.
Definition: formatter.h:46
#define __glibcxx_check_erase_range(_First, _Last)
Definition: macros.h:169