libstdc++
debug/list
Go to the documentation of this file.
1 // Debugging list implementation -*- C++ -*-
2 
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.
11 
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.
16 
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.
20 
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/>.
25 
26 /** @file debug/list
27  * This file is a GNU debug extension to the Standard C++ Library.
28  */
29 
30 #ifndef _GLIBCXX_DEBUG_LIST
31 #define _GLIBCXX_DEBUG_LIST 1
32 
33 #include <list>
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::list with safety/checking/debug instrumentation.
42  template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
43  class list
44  : public _GLIBCXX_STD_C::list<_Tp, _Allocator>,
45  public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
46  {
47  typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base;
49 
50  typedef typename _Base::iterator _Base_iterator;
54  public:
55  typedef typename _Base::reference reference;
56  typedef typename _Base::const_reference const_reference;
57 
59  iterator;
62 
63  typedef typename _Base::size_type size_type;
64  typedef typename _Base::difference_type difference_type;
65 
66  typedef _Tp value_type;
67  typedef _Allocator allocator_type;
68  typedef typename _Base::pointer pointer;
69  typedef typename _Base::const_pointer const_pointer;
72 
73  // 23.2.2.1 construct/copy/destroy:
74  explicit
75  list(const _Allocator& __a = _Allocator())
76  : _Base(__a) { }
77 
78 #ifdef __GXX_EXPERIMENTAL_CXX0X__
79  explicit
80  list(size_type __n)
81  : _Base(__n) { }
82 
83  list(size_type __n, const _Tp& __value,
84  const _Allocator& __a = _Allocator())
85  : _Base(__n, __value, __a) { }
86 #else
87  explicit
88  list(size_type __n, const _Tp& __value = _Tp(),
89  const _Allocator& __a = _Allocator())
90  : _Base(__n, __value, __a) { }
91 #endif
92 
93  template<class _InputIterator>
94  list(_InputIterator __first, _InputIterator __last,
95  const _Allocator& __a = _Allocator())
96  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
97  __last)),
98  __gnu_debug::__base(__last), __a)
99  { }
100 
101 
102  list(const list& __x)
103  : _Base(__x), _Safe_base() { }
104 
105  list(const _Base& __x)
106  : _Base(__x), _Safe_base() { }
107 
108 #ifdef __GXX_EXPERIMENTAL_CXX0X__
109  list(list&& __x)
110  : _Base(std::move(__x)), _Safe_base()
111  { this->_M_swap(__x); }
112 
114  const allocator_type& __a = allocator_type())
115  : _Base(__l, __a), _Safe_base() { }
116 #endif
117 
118  ~list() { }
119 
120  list&
121  operator=(const list& __x)
122  {
123  static_cast<_Base&>(*this) = __x;
124  this->_M_invalidate_all();
125  return *this;
126  }
127 
128 #ifdef __GXX_EXPERIMENTAL_CXX0X__
129  list&
130  operator=(list&& __x)
131  {
132  // NB: DR 1204.
133  // NB: DR 675.
134  clear();
135  swap(__x);
136  return *this;
137  }
138 
139  list&
140  operator=(initializer_list<value_type> __l)
141  {
142  static_cast<_Base&>(*this) = __l;
143  this->_M_invalidate_all();
144  return *this;
145  }
146 
147  void
148  assign(initializer_list<value_type> __l)
149  {
150  _Base::assign(__l);
151  this->_M_invalidate_all();
152  }
153 #endif
154 
155  template<class _InputIterator>
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  using _Base::get_allocator;
173 
174  // iterators:
175  iterator
176  begin()
177  { return iterator(_Base::begin(), this); }
178 
180  begin() const
181  { return const_iterator(_Base::begin(), this); }
182 
183  iterator
184  end()
185  { return iterator(_Base::end(), this); }
186 
188  end() const
189  { return const_iterator(_Base::end(), this); }
190 
192  rbegin()
193  { return reverse_iterator(end()); }
194 
196  rbegin() const
197  { return const_reverse_iterator(end()); }
198 
200  rend()
201  { return reverse_iterator(begin()); }
202 
204  rend() const
205  { return const_reverse_iterator(begin()); }
206 
207 #ifdef __GXX_EXPERIMENTAL_CXX0X__
209  cbegin() const
210  { return const_iterator(_Base::begin(), this); }
211 
213  cend() const
214  { return const_iterator(_Base::end(), this); }
215 
217  crbegin() const
218  { return const_reverse_iterator(end()); }
219 
221  crend() const
222  { return const_reverse_iterator(begin()); }
223 #endif
224 
225  // 23.2.2.2 capacity:
226  using _Base::empty;
227  using _Base::size;
228  using _Base::max_size;
229 
230 #ifdef __GXX_EXPERIMENTAL_CXX0X__
231  void
232  resize(size_type __sz)
233  {
234  this->_M_detach_singular();
235 
236  // if __sz < size(), invalidate all iterators in [begin+__sz, end())
237  _Base_iterator __victim = _Base::begin();
238  _Base_iterator __end = _Base::end();
239  for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
240  ++__victim;
241 
242  for (; __victim != __end; ++__victim)
243  {
244  this->_M_invalidate_if(_Equal(__victim));
245  }
246 
247  __try
248  {
249  _Base::resize(__sz);
250  }
251  __catch(...)
252  {
253  this->_M_revalidate_singular();
254  __throw_exception_again;
255  }
256  }
257 
258  void
259  resize(size_type __sz, const _Tp& __c)
260  {
261  this->_M_detach_singular();
262 
263  // if __sz < size(), invalidate all iterators in [begin+__sz, end())
264  _Base_iterator __victim = _Base::begin();
265  _Base_iterator __end = _Base::end();
266  for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
267  ++__victim;
268 
269  for (; __victim != __end; ++__victim)
270  {
271  this->_M_invalidate_if(_Equal(__victim));
272  }
273 
274  __try
275  {
276  _Base::resize(__sz, __c);
277  }
278  __catch(...)
279  {
280  this->_M_revalidate_singular();
281  __throw_exception_again;
282  }
283  }
284 #else
285  void
286  resize(size_type __sz, _Tp __c = _Tp())
287  {
288  this->_M_detach_singular();
289 
290  // if __sz < size(), invalidate all iterators in [begin+__sz, end())
291  _Base_iterator __victim = _Base::begin();
292  _Base_iterator __end = _Base::end();
293  for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
294  ++__victim;
295 
296  for (; __victim != __end; ++__victim)
297  {
298  this->_M_invalidate_if(_Equal(__victim));
299  }
300 
301  __try
302  {
303  _Base::resize(__sz, __c);
304  }
305  __catch(...)
306  {
307  this->_M_revalidate_singular();
308  __throw_exception_again;
309  }
310  }
311 #endif
312 
313  // element access:
314  reference
315  front()
316  {
317  __glibcxx_check_nonempty();
318  return _Base::front();
319  }
320 
321  const_reference
322  front() const
323  {
324  __glibcxx_check_nonempty();
325  return _Base::front();
326  }
327 
328  reference
329  back()
330  {
331  __glibcxx_check_nonempty();
332  return _Base::back();
333  }
334 
335  const_reference
336  back() const
337  {
338  __glibcxx_check_nonempty();
339  return _Base::back();
340  }
341 
342  // 23.2.2.3 modifiers:
343  using _Base::push_front;
344 
345 #ifdef __GXX_EXPERIMENTAL_CXX0X__
346  using _Base::emplace_front;
347 #endif
348 
349  void
350  pop_front()
351  {
352  __glibcxx_check_nonempty();
353  this->_M_invalidate_if(_Equal(_Base::begin()));
354  _Base::pop_front();
355  }
356 
357  using _Base::push_back;
358 
359 #ifdef __GXX_EXPERIMENTAL_CXX0X__
360  using _Base::emplace_back;
361 #endif
362 
363  void
364  pop_back()
365  {
366  __glibcxx_check_nonempty();
367  this->_M_invalidate_if(_Equal(--_Base::end()));
368  _Base::pop_back();
369  }
370 
371 #ifdef __GXX_EXPERIMENTAL_CXX0X__
372  template<typename... _Args>
373  iterator
374  emplace(iterator __position, _Args&&... __args)
375  {
376  __glibcxx_check_insert(__position);
377  return iterator(_Base::emplace(__position.base(),
378  std::forward<_Args>(__args)...), this);
379  }
380 #endif
381 
382  iterator
383  insert(iterator __position, const _Tp& __x)
384  {
385  __glibcxx_check_insert(__position);
386  return iterator(_Base::insert(__position.base(), __x), this);
387  }
388 
389 #ifdef __GXX_EXPERIMENTAL_CXX0X__
390  iterator
391  insert(iterator __position, _Tp&& __x)
392  { return emplace(__position, std::move(__x)); }
393 
394  void
395  insert(iterator __p, initializer_list<value_type> __l)
396  {
398  _Base::insert(__p, __l);
399  }
400 #endif
401 
402  void
403  insert(iterator __position, size_type __n, const _Tp& __x)
404  {
405  __glibcxx_check_insert(__position);
406  _Base::insert(__position.base(), __n, __x);
407  }
408 
409  template<class _InputIterator>
410  void
411  insert(iterator __position, _InputIterator __first,
412  _InputIterator __last)
413  {
414  __glibcxx_check_insert_range(__position, __first, __last);
415  _Base::insert(__position.base(), __gnu_debug::__base(__first),
416  __gnu_debug::__base(__last));
417  }
418 
419  private:
421  _M_erase(_Base_iterator __position)
422  {
423  this->_M_invalidate_if(_Equal(__position));
424  return _Base::erase(__position);
425  }
426  public:
427  iterator
428  erase(iterator __position)
429  {
430  __glibcxx_check_erase(__position);
431  return iterator(_M_erase(__position.base()), this);
432  }
433 
434  iterator
435  erase(iterator __position, iterator __last)
436  {
437  // _GLIBCXX_RESOLVE_LIB_DEFECTS
438  // 151. can't currently clear() empty container
439  __glibcxx_check_erase_range(__position, __last);
440  for (_Base_iterator __victim = __position.base();
441  __victim != __last.base(); ++__victim)
442  {
443  _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
444  _M_message(__gnu_debug::__msg_valid_range)
445  ._M_iterator(__position, "position")
446  ._M_iterator(__last, "last"));
447  this->_M_invalidate_if(_Equal(__victim));
448  }
449  return iterator(_Base::erase(__position.base(), __last.base()), this);
450  }
451 
452  void
453  swap(list& __x)
454  {
455  _Base::swap(__x);
456  this->_M_swap(__x);
457  }
458 
459  void
460  clear()
461  {
462  _Base::clear();
463  this->_M_invalidate_all();
464  }
465 
466  // 23.2.2.4 list operations:
467  void
468 #ifdef __GXX_EXPERIMENTAL_CXX0X__
469  splice(iterator __position, list&& __x)
470 #else
471  splice(iterator __position, list& __x)
472 #endif
473  {
474  _GLIBCXX_DEBUG_VERIFY(&__x != this,
475  _M_message(__gnu_debug::__msg_self_splice)
476  ._M_sequence(*this, "this"));
477  this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
478  _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()));
479  }
480 
481 #ifdef __GXX_EXPERIMENTAL_CXX0X__
482  void
483  splice(iterator __position, list& __x)
484  { splice(__position, std::move(__x)); }
485 #endif
486 
487  void
488 #ifdef __GXX_EXPERIMENTAL_CXX0X__
489  splice(iterator __position, list&& __x, iterator __i)
490 #else
491  splice(iterator __position, list& __x, iterator __i)
492 #endif
493  {
494  __glibcxx_check_insert(__position);
495 
496  // We used to perform the splice_alloc check: not anymore, redundant
497  // after implementing the relevant bits of N1599.
498 
500  _M_message(__gnu_debug::__msg_splice_bad)
501  ._M_iterator(__i, "__i"));
503  _M_message(__gnu_debug::__msg_splice_other)
504  ._M_iterator(__i, "__i")._M_sequence(__x, "__x"));
505 
506  // _GLIBCXX_RESOLVE_LIB_DEFECTS
507  // 250. splicing invalidates iterators
508  this->_M_transfer_from_if(__x, _Equal(__i.base()));
509  _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
510  __i.base());
511  }
512 
513 #ifdef __GXX_EXPERIMENTAL_CXX0X__
514  void
515  splice(iterator __position, list& __x, iterator __i)
516  { splice(__position, std::move(__x), __i); }
517 #endif
518 
519  void
520 #ifdef __GXX_EXPERIMENTAL_CXX0X__
521  splice(iterator __position, list&& __x, iterator __first,
522  iterator __last)
523 #else
524  splice(iterator __position, list& __x, iterator __first,
525  iterator __last)
526 #endif
527  {
528  __glibcxx_check_insert(__position);
529  __glibcxx_check_valid_range(__first, __last);
531  _M_message(__gnu_debug::__msg_splice_other)
532  ._M_sequence(__x, "x")
533  ._M_iterator(__first, "first"));
534 
535  // We used to perform the splice_alloc check: not anymore, redundant
536  // after implementing the relevant bits of N1599.
537 
538  for (_Base_iterator __tmp = __first.base();
539  __tmp != __last.base(); ++__tmp)
540  {
541  _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
542  _M_message(__gnu_debug::__msg_valid_range)
543  ._M_iterator(__first, "first")
544  ._M_iterator(__last, "last"));
545  _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position,
546  _M_message(__gnu_debug::__msg_splice_overlap)
547  ._M_iterator(__tmp, "position")
548  ._M_iterator(__first, "first")
549  ._M_iterator(__last, "last"));
550  // _GLIBCXX_RESOLVE_LIB_DEFECTS
551  // 250. splicing invalidates iterators
552  this->_M_transfer_from_if(__x, _Equal(__tmp));
553  }
554 
555  _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
556  __first.base(), __last.base());
557  }
558 
559 #ifdef __GXX_EXPERIMENTAL_CXX0X__
560  void
561  splice(iterator __position, list& __x, iterator __first, iterator __last)
562  { splice(__position, std::move(__x), __first, __last); }
563 #endif
564 
565  void
566  remove(const _Tp& __value)
567  {
568  for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); )
569  {
570  if (*__x == __value)
571  __x = _M_erase(__x);
572  else
573  ++__x;
574  }
575  }
576 
577  template<class _Predicate>
578  void
579  remove_if(_Predicate __pred)
580  {
581  for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); )
582  {
583  if (__pred(*__x))
584  __x = _M_erase(__x);
585  else
586  ++__x;
587  }
588  }
589 
590  void
591  unique()
592  {
593  _Base_iterator __first = _Base::begin();
594  _Base_iterator __last = _Base::end();
595  if (__first == __last)
596  return;
597  _Base_iterator __next = __first; ++__next;
598  while (__next != __last)
599  {
600  if (*__first == *__next)
601  __next = _M_erase(__next);
602  else
603  __first = __next++;
604  }
605  }
606 
607  template<class _BinaryPredicate>
608  void
609  unique(_BinaryPredicate __binary_pred)
610  {
611  _Base_iterator __first = _Base::begin();
612  _Base_iterator __last = _Base::end();
613  if (__first == __last)
614  return;
615  _Base_iterator __next = __first; ++__next;
616  while (__next != __last)
617  {
618  if (__binary_pred(*__first, *__next))
619  __next = _M_erase(__next);
620  else
621  __first = __next++;
622  }
623  }
624 
625  void
626 #ifdef __GXX_EXPERIMENTAL_CXX0X__
627  merge(list&& __x)
628 #else
629  merge(list& __x)
630 #endif
631  {
632  // _GLIBCXX_RESOLVE_LIB_DEFECTS
633  // 300. list::merge() specification incomplete
634  if (this != &__x)
635  {
636  __glibcxx_check_sorted(_Base::begin(), _Base::end());
637  __glibcxx_check_sorted(__x.begin().base(), __x.end().base());
638  this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
639  _Base::merge(_GLIBCXX_MOVE(__x._M_base()));
640  }
641  }
642 
643 #ifdef __GXX_EXPERIMENTAL_CXX0X__
644  void
645  merge(list& __x)
646  { merge(std::move(__x)); }
647 #endif
648 
649  template<class _Compare>
650  void
651 #ifdef __GXX_EXPERIMENTAL_CXX0X__
652  merge(list&& __x, _Compare __comp)
653 #else
654  merge(list& __x, _Compare __comp)
655 #endif
656  {
657  // _GLIBCXX_RESOLVE_LIB_DEFECTS
658  // 300. list::merge() specification incomplete
659  if (this != &__x)
660  {
661  __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(),
662  __comp);
663  __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(),
664  __comp);
665  this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
666  _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp);
667  }
668  }
669 
670 #ifdef __GXX_EXPERIMENTAL_CXX0X__
671  template<typename _Compare>
672  void
673  merge(list& __x, _Compare __comp)
674  { merge(std::move(__x), __comp); }
675 #endif
676 
677  void
678  sort() { _Base::sort(); }
679 
680  template<typename _StrictWeakOrdering>
681  void
682  sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
683 
684  using _Base::reverse;
685 
686  _Base&
687  _M_base() { return *this; }
688 
689  const _Base&
690  _M_base() const { return *this; }
691 
692  private:
693  void
694  _M_invalidate_all()
695  {
696  this->_M_invalidate_if(_Not_equal(_Base::end()));
697  }
698  };
699 
700  template<typename _Tp, typename _Alloc>
701  inline bool
702  operator==(const list<_Tp, _Alloc>& __lhs,
703  const list<_Tp, _Alloc>& __rhs)
704  { return __lhs._M_base() == __rhs._M_base(); }
705 
706  template<typename _Tp, typename _Alloc>
707  inline bool
708  operator!=(const list<_Tp, _Alloc>& __lhs,
709  const list<_Tp, _Alloc>& __rhs)
710  { return __lhs._M_base() != __rhs._M_base(); }
711 
712  template<typename _Tp, typename _Alloc>
713  inline bool
714  operator<(const list<_Tp, _Alloc>& __lhs,
715  const list<_Tp, _Alloc>& __rhs)
716  { return __lhs._M_base() < __rhs._M_base(); }
717 
718  template<typename _Tp, typename _Alloc>
719  inline bool
720  operator<=(const list<_Tp, _Alloc>& __lhs,
721  const list<_Tp, _Alloc>& __rhs)
722  { return __lhs._M_base() <= __rhs._M_base(); }
723 
724  template<typename _Tp, typename _Alloc>
725  inline bool
726  operator>=(const list<_Tp, _Alloc>& __lhs,
727  const list<_Tp, _Alloc>& __rhs)
728  { return __lhs._M_base() >= __rhs._M_base(); }
729 
730  template<typename _Tp, typename _Alloc>
731  inline bool
732  operator>(const list<_Tp, _Alloc>& __lhs,
733  const list<_Tp, _Alloc>& __rhs)
734  { return __lhs._M_base() > __rhs._M_base(); }
735 
736  template<typename _Tp, typename _Alloc>
737  inline void
738  swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
739  { __lhs.swap(__rhs); }
740 
741 } // namespace __debug
742 } // namespace std
743 
744 #endif