libstdc++
debug/deque
Go to the documentation of this file.
1 // Debugging deque 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/deque
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_DEQUE
30 #define _GLIBCXX_DEBUG_DEQUE 1
31 
32 #include <deque>
33 #include <debug/safe_sequence.h>
34 #include <debug/safe_iterator.h>
35 
36 namespace std _GLIBCXX_VISIBILITY(default)
37 {
38 namespace __debug
39 {
40  /// Class std::deque with safety/checking/debug instrumentation.
41  template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
42  class deque
43  : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>,
44  public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
45  {
46  typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base;
47 
49  typedef typename _Base::iterator _Base_iterator;
51  public:
52  typedef typename _Base::reference reference;
53  typedef typename _Base::const_reference const_reference;
54 
56  iterator;
59 
60  typedef typename _Base::size_type size_type;
61  typedef typename _Base::difference_type difference_type;
62 
63  typedef _Tp value_type;
64  typedef _Allocator allocator_type;
65  typedef typename _Base::pointer pointer;
66  typedef typename _Base::const_pointer const_pointer;
69 
70  // 23.2.1.1 construct/copy/destroy:
71  explicit
72  deque(const _Allocator& __a = _Allocator())
73  : _Base(__a) { }
74 
75 #if __cplusplus >= 201103L
76  explicit
77  deque(size_type __n)
78  : _Base(__n) { }
79 
80  deque(size_type __n, const _Tp& __value,
81  const _Allocator& __a = _Allocator())
82  : _Base(__n, __value, __a) { }
83 #else
84  explicit
85  deque(size_type __n, const _Tp& __value = _Tp(),
86  const _Allocator& __a = _Allocator())
87  : _Base(__n, __value, __a) { }
88 #endif
89 
90 #if __cplusplus >= 201103L
91  template<class _InputIterator,
92  typename = std::_RequireInputIter<_InputIterator>>
93 #else
94  template<class _InputIterator>
95 #endif
96  deque(_InputIterator __first, _InputIterator __last,
97  const _Allocator& __a = _Allocator())
98  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
99  __last)),
100  __gnu_debug::__base(__last), __a)
101  { }
102 
103  deque(const deque& __x)
104  : _Base(__x) { }
105 
106  deque(const _Base& __x)
107  : _Base(__x) { }
108 
109 #if __cplusplus >= 201103L
110  deque(deque&& __x)
111  : _Base(std::move(__x))
112  { this->_M_swap(__x); }
113 
115  const allocator_type& __a = allocator_type())
116  : _Base(__l, __a) { }
117 #endif
118 
119  ~deque() _GLIBCXX_NOEXCEPT { }
120 
121  deque&
122  operator=(const deque& __x)
123  {
124  *static_cast<_Base*>(this) = __x;
125  this->_M_invalidate_all();
126  return *this;
127  }
128 
129 #if __cplusplus >= 201103L
130  deque&
131  operator=(deque&& __x) noexcept
132  {
133  // NB: DR 1204.
134  // NB: DR 675.
135  __glibcxx_check_self_move_assign(__x);
136  clear();
137  swap(__x);
138  return *this;
139  }
140 
141  deque&
142  operator=(initializer_list<value_type> __l)
143  {
144  *static_cast<_Base*>(this) = __l;
145  this->_M_invalidate_all();
146  return *this;
147  }
148 #endif
149 
150 #if __cplusplus >= 201103L
151  template<class _InputIterator,
152  typename = std::_RequireInputIter<_InputIterator>>
153 #else
154  template<class _InputIterator>
155 #endif
156  void
157  assign(_InputIterator __first, _InputIterator __last)
158  {
159  __glibcxx_check_valid_range(__first, __last);
160  _Base::assign(__gnu_debug::__base(__first),
161  __gnu_debug::__base(__last));
162  this->_M_invalidate_all();
163  }
164 
165  void
166  assign(size_type __n, const _Tp& __t)
167  {
168  _Base::assign(__n, __t);
169  this->_M_invalidate_all();
170  }
171 
172 #if __cplusplus >= 201103L
173  void
174  assign(initializer_list<value_type> __l)
175  {
176  _Base::assign(__l);
177  this->_M_invalidate_all();
178  }
179 #endif
180 
181  using _Base::get_allocator;
182 
183  // iterators:
184  iterator
185  begin() _GLIBCXX_NOEXCEPT
186  { return iterator(_Base::begin(), this); }
187 
189  begin() const _GLIBCXX_NOEXCEPT
190  { return const_iterator(_Base::begin(), this); }
191 
192  iterator
193  end() _GLIBCXX_NOEXCEPT
194  { return iterator(_Base::end(), this); }
195 
197  end() const _GLIBCXX_NOEXCEPT
198  { return const_iterator(_Base::end(), this); }
199 
201  rbegin() _GLIBCXX_NOEXCEPT
202  { return reverse_iterator(end()); }
203 
205  rbegin() const _GLIBCXX_NOEXCEPT
206  { return const_reverse_iterator(end()); }
207 
209  rend() _GLIBCXX_NOEXCEPT
210  { return reverse_iterator(begin()); }
211 
213  rend() const _GLIBCXX_NOEXCEPT
214  { return const_reverse_iterator(begin()); }
215 
216 #if __cplusplus >= 201103L
218  cbegin() const noexcept
219  { return const_iterator(_Base::begin(), this); }
220 
222  cend() const noexcept
223  { return const_iterator(_Base::end(), this); }
224 
226  crbegin() const noexcept
227  { return const_reverse_iterator(end()); }
228 
230  crend() const noexcept
231  { return const_reverse_iterator(begin()); }
232 #endif
233 
234  private:
235  void
236  _M_invalidate_after_nth(difference_type __n)
237  {
239  this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
240  }
241 
242  public:
243  // 23.2.1.2 capacity:
244  using _Base::size;
245  using _Base::max_size;
246 
247 #if __cplusplus >= 201103L
248  void
249  resize(size_type __sz)
250  {
251  bool __invalidate_all = __sz > this->size();
252  if (__sz < this->size())
253  this->_M_invalidate_after_nth(__sz);
254 
255  _Base::resize(__sz);
256 
257  if (__invalidate_all)
258  this->_M_invalidate_all();
259  }
260 
261  void
262  resize(size_type __sz, const _Tp& __c)
263  {
264  bool __invalidate_all = __sz > this->size();
265  if (__sz < this->size())
266  this->_M_invalidate_after_nth(__sz);
267 
268  _Base::resize(__sz, __c);
269 
270  if (__invalidate_all)
271  this->_M_invalidate_all();
272  }
273 #else
274  void
275  resize(size_type __sz, _Tp __c = _Tp())
276  {
277  bool __invalidate_all = __sz > this->size();
278  if (__sz < this->size())
279  this->_M_invalidate_after_nth(__sz);
280 
281  _Base::resize(__sz, __c);
282 
283  if (__invalidate_all)
284  this->_M_invalidate_all();
285  }
286 #endif
287 
288 #if __cplusplus >= 201103L
289  void
290  shrink_to_fit() noexcept
291  {
292  if (_Base::_M_shrink_to_fit())
293  this->_M_invalidate_all();
294  }
295 #endif
296 
297  using _Base::empty;
298 
299  // element access:
300  reference
301  operator[](size_type __n) _GLIBCXX_NOEXCEPT
302  {
303  __glibcxx_check_subscript(__n);
304  return _M_base()[__n];
305  }
306 
307  const_reference
308  operator[](size_type __n) const _GLIBCXX_NOEXCEPT
309  {
310  __glibcxx_check_subscript(__n);
311  return _M_base()[__n];
312  }
313 
314  using _Base::at;
315 
316  reference
317  front() _GLIBCXX_NOEXCEPT
318  {
319  __glibcxx_check_nonempty();
320  return _Base::front();
321  }
322 
323  const_reference
324  front() const _GLIBCXX_NOEXCEPT
325  {
326  __glibcxx_check_nonempty();
327  return _Base::front();
328  }
329 
330  reference
331  back() _GLIBCXX_NOEXCEPT
332  {
333  __glibcxx_check_nonempty();
334  return _Base::back();
335  }
336 
337  const_reference
338  back() const _GLIBCXX_NOEXCEPT
339  {
340  __glibcxx_check_nonempty();
341  return _Base::back();
342  }
343 
344  // 23.2.1.3 modifiers:
345  void
346  push_front(const _Tp& __x)
347  {
348  _Base::push_front(__x);
349  this->_M_invalidate_all();
350  }
351 
352  void
353  push_back(const _Tp& __x)
354  {
355  _Base::push_back(__x);
356  this->_M_invalidate_all();
357  }
358 
359 #if __cplusplus >= 201103L
360  void
361  push_front(_Tp&& __x)
362  { emplace_front(std::move(__x)); }
363 
364  void
365  push_back(_Tp&& __x)
366  { emplace_back(std::move(__x)); }
367 
368  template<typename... _Args>
369  void
370  emplace_front(_Args&&... __args)
371  {
372  _Base::emplace_front(std::forward<_Args>(__args)...);
373  this->_M_invalidate_all();
374  }
375 
376  template<typename... _Args>
377  void
378  emplace_back(_Args&&... __args)
379  {
380  _Base::emplace_back(std::forward<_Args>(__args)...);
381  this->_M_invalidate_all();
382  }
383 
384  template<typename... _Args>
385  iterator
386  emplace(const_iterator __position, _Args&&... __args)
387  {
388  __glibcxx_check_insert(__position);
389  _Base_iterator __res = _Base::emplace(__position.base(),
390  std::forward<_Args>(__args)...);
391  this->_M_invalidate_all();
392  return iterator(__res, this);
393  }
394 #endif
395 
396  iterator
397 #if __cplusplus >= 201103L
398  insert(const_iterator __position, const _Tp& __x)
399 #else
400  insert(iterator __position, const _Tp& __x)
401 #endif
402  {
403  __glibcxx_check_insert(__position);
404  _Base_iterator __res = _Base::insert(__position.base(), __x);
405  this->_M_invalidate_all();
406  return iterator(__res, this);
407  }
408 
409 #if __cplusplus >= 201103L
410  iterator
411  insert(const_iterator __position, _Tp&& __x)
412  { return emplace(__position, std::move(__x)); }
413 
414  iterator
415  insert(const_iterator __position, initializer_list<value_type> __l)
416  {
417  __glibcxx_check_insert(__position);
418  _Base_iterator __res = _Base::insert(__position.base(), __l);
419  this->_M_invalidate_all();
420  return iterator(__res, this);
421  }
422 #endif
423 
424 #if __cplusplus >= 201103L
425  iterator
426  insert(const_iterator __position, size_type __n, const _Tp& __x)
427  {
428  __glibcxx_check_insert(__position);
429  _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
430  this->_M_invalidate_all();
431  return iterator(__res, this);
432  }
433 #else
434  void
435  insert(iterator __position, size_type __n, const _Tp& __x)
436  {
437  __glibcxx_check_insert(__position);
438  _Base::insert(__position.base(), __n, __x);
439  this->_M_invalidate_all();
440  }
441 #endif
442 
443 #if __cplusplus >= 201103L
444  template<class _InputIterator,
445  typename = std::_RequireInputIter<_InputIterator>>
446  iterator
447  insert(const_iterator __position,
448  _InputIterator __first, _InputIterator __last)
449  {
450  __glibcxx_check_insert_range(__position, __first, __last);
451  _Base_iterator __res = _Base::insert(__position.base(),
452  __gnu_debug::__base(__first),
453  __gnu_debug::__base(__last));
454  this->_M_invalidate_all();
455  return iterator(__res, this);
456  }
457 #else
458  template<class _InputIterator>
459  void
460  insert(iterator __position,
461  _InputIterator __first, _InputIterator __last)
462  {
463  __glibcxx_check_insert_range(__position, __first, __last);
464  _Base::insert(__position.base(), __gnu_debug::__base(__first),
465  __gnu_debug::__base(__last));
466  this->_M_invalidate_all();
467  }
468 #endif
469 
470  void
471  pop_front() _GLIBCXX_NOEXCEPT
472  {
473  __glibcxx_check_nonempty();
474  this->_M_invalidate_if(_Equal(_Base::begin()));
475  _Base::pop_front();
476  }
477 
478  void
479  pop_back() _GLIBCXX_NOEXCEPT
480  {
481  __glibcxx_check_nonempty();
482  this->_M_invalidate_if(_Equal(--_Base::end()));
483  _Base::pop_back();
484  }
485 
486  iterator
487 #if __cplusplus >= 201103L
488  erase(const_iterator __position)
489 #else
490  erase(iterator __position)
491 #endif
492  {
493  __glibcxx_check_erase(__position);
494 #if __cplusplus >= 201103L
495  _Base_const_iterator __victim = __position.base();
496 #else
497  _Base_iterator __victim = __position.base();
498 #endif
499  if (__victim == _Base::begin() || __victim == _Base::end() - 1)
500  {
501  this->_M_invalidate_if(_Equal(__victim));
502  return iterator(_Base::erase(__victim), this);
503  }
504  else
505  {
506  _Base_iterator __res = _Base::erase(__victim);
507  this->_M_invalidate_all();
508  return iterator(__res, this);
509  }
510  }
511 
512  iterator
513 #if __cplusplus >= 201103L
514  erase(const_iterator __first, const_iterator __last)
515 #else
516  erase(iterator __first, iterator __last)
517 #endif
518  {
519  // _GLIBCXX_RESOLVE_LIB_DEFECTS
520  // 151. can't currently clear() empty container
521  __glibcxx_check_erase_range(__first, __last);
522 
523  if (__first.base() == __last.base())
524 #if __cplusplus >= 201103L
525  return iterator(__first.base()._M_const_cast(), this);
526 #else
527  return __first;
528 #endif
529  else if (__first.base() == _Base::begin()
530  || __last.base() == _Base::end())
531  {
532  this->_M_detach_singular();
533  for (_Base_const_iterator __position = __first.base();
534  __position != __last.base(); ++__position)
535  {
536  this->_M_invalidate_if(_Equal(__position));
537  }
538  __try
539  {
540  return iterator(_Base::erase(__first.base(), __last.base()),
541  this);
542  }
543  __catch(...)
544  {
545  this->_M_revalidate_singular();
546  __throw_exception_again;
547  }
548  }
549  else
550  {
551  _Base_iterator __res = _Base::erase(__first.base(),
552  __last.base());
553  this->_M_invalidate_all();
554  return iterator(__res, this);
555  }
556  }
557 
558  void
559  swap(deque& __x) _GLIBCXX_NOEXCEPT
560  {
561  _Base::swap(__x);
562  this->_M_swap(__x);
563  }
564 
565  void
566  clear() _GLIBCXX_NOEXCEPT
567  {
568  _Base::clear();
569  this->_M_invalidate_all();
570  }
571 
572  _Base&
573  _M_base() _GLIBCXX_NOEXCEPT { return *this; }
574 
575  const _Base&
576  _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
577  };
578 
579  template<typename _Tp, typename _Alloc>
580  inline bool
581  operator==(const deque<_Tp, _Alloc>& __lhs,
582  const deque<_Tp, _Alloc>& __rhs)
583  { return __lhs._M_base() == __rhs._M_base(); }
584 
585  template<typename _Tp, typename _Alloc>
586  inline bool
587  operator!=(const deque<_Tp, _Alloc>& __lhs,
588  const deque<_Tp, _Alloc>& __rhs)
589  { return __lhs._M_base() != __rhs._M_base(); }
590 
591  template<typename _Tp, typename _Alloc>
592  inline bool
593  operator<(const deque<_Tp, _Alloc>& __lhs,
594  const deque<_Tp, _Alloc>& __rhs)
595  { return __lhs._M_base() < __rhs._M_base(); }
596 
597  template<typename _Tp, typename _Alloc>
598  inline bool
599  operator<=(const deque<_Tp, _Alloc>& __lhs,
600  const deque<_Tp, _Alloc>& __rhs)
601  { return __lhs._M_base() <= __rhs._M_base(); }
602 
603  template<typename _Tp, typename _Alloc>
604  inline bool
605  operator>=(const deque<_Tp, _Alloc>& __lhs,
606  const deque<_Tp, _Alloc>& __rhs)
607  { return __lhs._M_base() >= __rhs._M_base(); }
608 
609  template<typename _Tp, typename _Alloc>
610  inline bool
611  operator>(const deque<_Tp, _Alloc>& __lhs,
612  const deque<_Tp, _Alloc>& __rhs)
613  { return __lhs._M_base() > __rhs._M_base(); }
614 
615  template<typename _Tp, typename _Alloc>
616  inline void
617  swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs)
618  { __lhs.swap(__rhs); }
619 
620 } // namespace __debug
621 } // namespace std
622 
623 #endif
#define __glibcxx_check_insert_range(_Position, _First, _Last)
Definition: macros.h:106
void _M_swap(_Safe_sequence_base &__x)
#define __glibcxx_check_insert(_Position)
Definition: macros.h:73
constexpr size_t size() const noexcept
Returns the total number of bits.
Definition: bitset:1293
_Iterator base() const noexcept
Return the underlying iterator.
#define __glibcxx_check_erase(_Position)
Definition: macros.h:141
void swap(function< _Res(_Args...)> &__x, function< _Res(_Args...)> &__y)
Swap the targets of two polymorphic function object wrappers.
Definition: functional:2534
initializer_list
Base class for constructing a safe sequence type that tracks iterators that reference it...
Definition: formatter.h:52
Class std::deque with safety/checking/debug instrumentation.
Definition: debug/deque:42
_Siter_base< _Iterator >::iterator_type __base(_Iterator __it)
Definition: functions.h:558
Safe iterator wrapper.
Definition: formatter.h:46
A standard container using fixed-size memory allocation and constant-time manipulation of elements at...
Definition: stl_deque.h:735
#define __glibcxx_check_erase_range(_First, _Last)
Definition: macros.h:169