1 // Debugging list implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005
4 // Free Software Foundation, Inc.
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 2, or (at your option)
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 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
31 #ifndef _GLIBCXX_DEBUG_LIST
32 #define _GLIBCXX_DEBUG_LIST 1
35 #include <bits/stl_algo.h>
36 #include <debug/safe_sequence.h>
37 #include <debug/safe_iterator.h>
39 namespace __gnu_debug_def
41 template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
43 : public _GLIBCXX_STD::list<_Tp, _Allocator>,
44 public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
46 typedef _GLIBCXX_STD::list<_Tp, _Allocator> _Base;
47 typedef __gnu_debug::_Safe_sequence<list> _Safe_base;
50 typedef typename _Base::reference reference;
51 typedef typename _Base::const_reference const_reference;
53 typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, list>
55 typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, list>
58 typedef typename _Base::size_type size_type;
59 typedef typename _Base::difference_type difference_type;
61 typedef _Tp value_type;
62 typedef _Allocator allocator_type;
63 typedef typename _Base::pointer pointer;
64 typedef typename _Base::const_pointer const_pointer;
65 typedef std::reverse_iterator<iterator> reverse_iterator;
66 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
68 // 23.2.2.1 construct/copy/destroy:
69 explicit list(const _Allocator& __a = _Allocator())
72 explicit list(size_type __n, const _Tp& __value = _Tp(),
73 const _Allocator& __a = _Allocator())
74 : _Base(__n, __value, __a) { }
76 template<class _InputIterator>
77 list(_InputIterator __first, _InputIterator __last,
78 const _Allocator& __a = _Allocator())
79 : _Base(__gnu_debug::__check_valid_range(__first, __last), __last, __a)
83 list(const list& __x) : _Base(__x), _Safe_base() { }
85 list(const _Base& __x) : _Base(__x), _Safe_base() { }
90 operator=(const list& __x)
92 static_cast<_Base&>(*this) = __x;
93 this->_M_invalidate_all();
97 template<class _InputIterator>
99 assign(_InputIterator __first, _InputIterator __last)
101 __glibcxx_check_valid_range(__first, __last);
102 _Base::assign(__first, __last);
103 this->_M_invalidate_all();
107 assign(size_type __n, const _Tp& __t)
109 _Base::assign(__n, __t);
110 this->_M_invalidate_all();
113 using _Base::get_allocator;
118 { return iterator(_Base::begin(), this); }
122 { return const_iterator(_Base::begin(), this); }
126 { return iterator(_Base::end(), this); }
130 { return const_iterator(_Base::end(), this); }
134 { return reverse_iterator(end()); }
136 const_reverse_iterator
138 { return const_reverse_iterator(end()); }
142 { return reverse_iterator(begin()); }
144 const_reverse_iterator
146 { return const_reverse_iterator(begin()); }
148 // 23.2.2.2 capacity:
151 using _Base::max_size;
154 resize(size_type __sz, _Tp __c = _Tp())
156 this->_M_detach_singular();
158 // if __sz < size(), invalidate all iterators in [begin+__sz, end())
159 iterator __victim = begin();
160 iterator __end = end();
161 for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
164 while (__victim != __end)
166 iterator __real_victim = __victim++;
167 __real_victim._M_invalidate();
172 _Base::resize(__sz, __c);
176 this->_M_revalidate_singular();
177 __throw_exception_again;
185 __glibcxx_check_nonempty();
186 return _Base::front();
192 __glibcxx_check_nonempty();
193 return _Base::front();
199 __glibcxx_check_nonempty();
200 return _Base::back();
206 __glibcxx_check_nonempty();
207 return _Base::back();
210 // 23.2.2.3 modifiers:
211 using _Base::push_front;
216 __glibcxx_check_nonempty();
217 iterator __victim = begin();
218 __victim._M_invalidate();
222 using _Base::push_back;
227 __glibcxx_check_nonempty();
228 iterator __victim = end();
230 __victim._M_invalidate();
235 insert(iterator __position, const _Tp& __x)
237 __glibcxx_check_insert(__position);
238 return iterator(_Base::insert(__position.base(), __x), this);
242 insert(iterator __position, size_type __n, const _Tp& __x)
244 __glibcxx_check_insert(__position);
245 _Base::insert(__position.base(), __n, __x);
248 template<class _InputIterator>
250 insert(iterator __position, _InputIterator __first,
251 _InputIterator __last)
253 __glibcxx_check_insert_range(__position, __first, __last);
254 _Base::insert(__position.base(), __first, __last);
258 erase(iterator __position)
260 __glibcxx_check_erase(__position);
261 __position._M_invalidate();
262 return iterator(_Base::erase(__position.base()), this);
266 erase(iterator __position, iterator __last)
268 // _GLIBCXX_RESOLVE_LIB_DEFECTS
269 // 151. can't currently clear() empty container
270 __glibcxx_check_erase_range(__position, __last);
271 for (iterator __victim = __position; __victim != __last; )
273 iterator __old = __victim;
275 __old._M_invalidate();
277 return iterator(_Base::erase(__position.base(), __last.base()), this);
291 this->_M_invalidate_all();
294 // 23.2.2.4 list operations:
296 splice(iterator __position, list& __x)
298 _GLIBCXX_DEBUG_VERIFY(&__x != this,
299 _M_message(::__gnu_debug::__msg_self_splice)
300 ._M_sequence(*this, "this"));
301 this->splice(__position, __x, __x.begin(), __x.end());
305 splice(iterator __position, list& __x, iterator __i)
307 __glibcxx_check_insert(__position);
308 _GLIBCXX_DEBUG_VERIFY(__x.get_allocator() == this->get_allocator(),
309 _M_message(::__gnu_debug::__msg_splice_alloc)
310 ._M_sequence(*this)._M_sequence(__x, "__x"));
311 _GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(),
312 _M_message(::__gnu_debug::__msg_splice_bad)
313 ._M_iterator(__i, "__i"));
314 _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x),
315 _M_message(::__gnu_debug::__msg_splice_other)
316 ._M_iterator(__i, "__i")._M_sequence(__x, "__x"));
318 // _GLIBCXX_RESOLVE_LIB_DEFECTS
319 // 250. splicing invalidates iterators
320 this->_M_transfer_iter(__i);
321 _Base::splice(__position.base(), __x._M_base(), __i.base());
325 splice(iterator __position, list& __x, iterator __first, iterator __last)
327 __glibcxx_check_insert(__position);
328 __glibcxx_check_valid_range(__first, __last);
329 _GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x),
330 _M_message(::__gnu_debug::__msg_splice_other)
331 ._M_sequence(__x, "x")
332 ._M_iterator(__first, "first"));
333 _GLIBCXX_DEBUG_VERIFY(__x.get_allocator() == this->get_allocator(),
334 _M_message(::__gnu_debug::__msg_splice_alloc)
335 ._M_sequence(*this)._M_sequence(__x));
337 for (iterator __tmp = __first; __tmp != __last; )
339 _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position,
340 _M_message(::__gnu_debug::__msg_splice_overlap)
341 ._M_iterator(__tmp, "position")
342 ._M_iterator(__first, "first")
343 ._M_iterator(__last, "last"));
344 iterator __victim = __tmp++;
345 // _GLIBCXX_RESOLVE_LIB_DEFECTS
346 // 250. splicing invalidates iterators
347 this->_M_transfer_iter(__victim);
350 _Base::splice(__position.base(), __x._M_base(), __first.base(),
355 remove(const _Tp& __value)
357 for (iterator __x = begin(); __x.base() != _Base::end(); )
366 template<class _Predicate>
368 remove_if(_Predicate __pred)
370 for (iterator __x = begin(); __x.base() != _Base::end(); )
382 iterator __first = begin();
383 iterator __last = end();
384 if (__first == __last)
386 iterator __next = __first;
387 while (++__next != __last)
389 if (*__first == *__next)
397 template<class _BinaryPredicate>
399 unique(_BinaryPredicate __binary_pred)
401 iterator __first = begin();
402 iterator __last = end();
403 if (__first == __last)
405 iterator __next = __first;
406 while (++__next != __last)
408 if (__binary_pred(*__first, *__next))
419 __glibcxx_check_sorted(_Base::begin(), _Base::end());
420 __glibcxx_check_sorted(__x.begin().base(), __x.end().base());
421 for (iterator __tmp = __x.begin(); __tmp != __x.end(); )
423 iterator __victim = __tmp++;
424 __victim._M_attach(&__x);
426 _Base::merge(__x._M_base());
429 template<class _Compare>
431 merge(list& __x, _Compare __comp)
433 __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp);
434 __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(),
436 for (iterator __tmp = __x.begin(); __tmp != __x.end(); )
438 iterator __victim = __tmp++;
439 __victim._M_attach(&__x);
441 _Base::merge(__x._M_base(), __comp);
445 sort() { _Base::sort(); }
447 template<typename _StrictWeakOrdering>
449 sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
451 using _Base::reverse;
454 _M_base() { return *this; }
457 _M_base() const { return *this; }
463 typedef typename _Base::const_iterator _Base_const_iterator;
464 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
465 this->_M_invalidate_if(_Not_equal(_M_base().end()));
469 template<typename _Tp, typename _Alloc>
471 operator==(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
472 { return __lhs._M_base() == __rhs._M_base(); }
474 template<typename _Tp, typename _Alloc>
476 operator!=(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
477 { return __lhs._M_base() != __rhs._M_base(); }
479 template<typename _Tp, typename _Alloc>
481 operator<(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
482 { return __lhs._M_base() < __rhs._M_base(); }
484 template<typename _Tp, typename _Alloc>
486 operator<=(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
487 { return __lhs._M_base() <= __rhs._M_base(); }
489 template<typename _Tp, typename _Alloc>
491 operator>=(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
492 { return __lhs._M_base() >= __rhs._M_base(); }
494 template<typename _Tp, typename _Alloc>
496 operator>(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
497 { return __lhs._M_base() > __rhs._M_base(); }
499 template<typename _Tp, typename _Alloc>
501 swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
502 { __lhs.swap(__rhs); }
503 } // namespace __gnu_debug_def