1 // Debugging list implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006
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>
43 template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
45 : public _GLIBCXX_STD::list<_Tp, _Allocator>,
46 public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
48 typedef _GLIBCXX_STD::list<_Tp, _Allocator> _Base;
49 typedef __gnu_debug::_Safe_sequence<list> _Safe_base;
52 typedef typename _Base::reference reference;
53 typedef typename _Base::const_reference const_reference;
55 typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, list>
57 typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, list>
60 typedef typename _Base::size_type size_type;
61 typedef typename _Base::difference_type difference_type;
63 typedef _Tp value_type;
64 typedef _Allocator allocator_type;
65 typedef typename _Base::pointer pointer;
66 typedef typename _Base::const_pointer const_pointer;
67 typedef std::reverse_iterator<iterator> reverse_iterator;
68 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
70 // 23.2.2.1 construct/copy/destroy:
71 explicit list(const _Allocator& __a = _Allocator())
74 explicit list(size_type __n, const _Tp& __value = _Tp(),
75 const _Allocator& __a = _Allocator())
76 : _Base(__n, __value, __a) { }
78 template<class _InputIterator>
79 list(_InputIterator __first, _InputIterator __last,
80 const _Allocator& __a = _Allocator())
81 : _Base(__gnu_debug::__check_valid_range(__first, __last), __last, __a)
85 list(const list& __x) : _Base(__x), _Safe_base() { }
87 list(const _Base& __x) : _Base(__x), _Safe_base() { }
92 operator=(const list& __x)
94 static_cast<_Base&>(*this) = __x;
95 this->_M_invalidate_all();
99 template<class _InputIterator>
101 assign(_InputIterator __first, _InputIterator __last)
103 __glibcxx_check_valid_range(__first, __last);
104 _Base::assign(__first, __last);
105 this->_M_invalidate_all();
109 assign(size_type __n, const _Tp& __t)
111 _Base::assign(__n, __t);
112 this->_M_invalidate_all();
115 using _Base::get_allocator;
120 { return iterator(_Base::begin(), this); }
124 { return const_iterator(_Base::begin(), this); }
128 { return iterator(_Base::end(), this); }
132 { return const_iterator(_Base::end(), this); }
136 { return reverse_iterator(end()); }
138 const_reverse_iterator
140 { return const_reverse_iterator(end()); }
144 { return reverse_iterator(begin()); }
146 const_reverse_iterator
148 { return const_reverse_iterator(begin()); }
150 // 23.2.2.2 capacity:
153 using _Base::max_size;
156 resize(size_type __sz, _Tp __c = _Tp())
158 this->_M_detach_singular();
160 // if __sz < size(), invalidate all iterators in [begin+__sz, end())
161 iterator __victim = begin();
162 iterator __end = end();
163 for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
166 while (__victim != __end)
168 iterator __real_victim = __victim++;
169 __real_victim._M_invalidate();
174 _Base::resize(__sz, __c);
178 this->_M_revalidate_singular();
179 __throw_exception_again;
187 __glibcxx_check_nonempty();
188 return _Base::front();
194 __glibcxx_check_nonempty();
195 return _Base::front();
201 __glibcxx_check_nonempty();
202 return _Base::back();
208 __glibcxx_check_nonempty();
209 return _Base::back();
212 // 23.2.2.3 modifiers:
213 using _Base::push_front;
218 __glibcxx_check_nonempty();
219 iterator __victim = begin();
220 __victim._M_invalidate();
224 using _Base::push_back;
229 __glibcxx_check_nonempty();
230 iterator __victim = end();
232 __victim._M_invalidate();
237 insert(iterator __position, const _Tp& __x)
239 __glibcxx_check_insert(__position);
240 return iterator(_Base::insert(__position.base(), __x), this);
244 insert(iterator __position, size_type __n, const _Tp& __x)
246 __glibcxx_check_insert(__position);
247 _Base::insert(__position.base(), __n, __x);
250 template<class _InputIterator>
252 insert(iterator __position, _InputIterator __first,
253 _InputIterator __last)
255 __glibcxx_check_insert_range(__position, __first, __last);
256 _Base::insert(__position.base(), __first, __last);
260 erase(iterator __position)
262 __glibcxx_check_erase(__position);
263 __position._M_invalidate();
264 return iterator(_Base::erase(__position.base()), this);
268 erase(iterator __position, iterator __last)
270 // _GLIBCXX_RESOLVE_LIB_DEFECTS
271 // 151. can't currently clear() empty container
272 __glibcxx_check_erase_range(__position, __last);
273 for (iterator __victim = __position; __victim != __last; )
275 iterator __old = __victim;
277 __old._M_invalidate();
279 return iterator(_Base::erase(__position.base(), __last.base()), this);
293 this->_M_invalidate_all();
296 // 23.2.2.4 list operations:
298 splice(iterator __position, list& __x)
300 _GLIBCXX_DEBUG_VERIFY(&__x != this,
301 _M_message(__gnu_debug::__msg_self_splice)
302 ._M_sequence(*this, "this"));
303 this->splice(__position, __x, __x.begin(), __x.end());
307 splice(iterator __position, list& __x, iterator __i)
309 __glibcxx_check_insert(__position);
311 // We used to perform the splice_alloc check: not anymore, redundant
312 // after implementing the relevant bits of N1599.
314 _GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(),
315 _M_message(__gnu_debug::__msg_splice_bad)
316 ._M_iterator(__i, "__i"));
317 _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x),
318 _M_message(__gnu_debug::__msg_splice_other)
319 ._M_iterator(__i, "__i")._M_sequence(__x, "__x"));
321 // _GLIBCXX_RESOLVE_LIB_DEFECTS
322 // 250. splicing invalidates iterators
323 this->_M_transfer_iter(__i);
324 _Base::splice(__position.base(), __x._M_base(), __i.base());
328 splice(iterator __position, list& __x, iterator __first, iterator __last)
330 __glibcxx_check_insert(__position);
331 __glibcxx_check_valid_range(__first, __last);
332 _GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x),
333 _M_message(__gnu_debug::__msg_splice_other)
334 ._M_sequence(__x, "x")
335 ._M_iterator(__first, "first"));
337 // We used to perform the splice_alloc check: not anymore, redundant
338 // after implementing the relevant bits of N1599.
340 for (iterator __tmp = __first; __tmp != __last; )
342 _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position,
343 _M_message(__gnu_debug::__msg_splice_overlap)
344 ._M_iterator(__tmp, "position")
345 ._M_iterator(__first, "first")
346 ._M_iterator(__last, "last"));
347 iterator __victim = __tmp++;
348 // _GLIBCXX_RESOLVE_LIB_DEFECTS
349 // 250. splicing invalidates iterators
350 this->_M_transfer_iter(__victim);
353 _Base::splice(__position.base(), __x._M_base(), __first.base(),
358 remove(const _Tp& __value)
360 for (iterator __x = begin(); __x.base() != _Base::end(); )
369 template<class _Predicate>
371 remove_if(_Predicate __pred)
373 for (iterator __x = begin(); __x.base() != _Base::end(); )
385 iterator __first = begin();
386 iterator __last = end();
387 if (__first == __last)
389 iterator __next = __first;
390 while (++__next != __last)
392 if (*__first == *__next)
400 template<class _BinaryPredicate>
402 unique(_BinaryPredicate __binary_pred)
404 iterator __first = begin();
405 iterator __last = end();
406 if (__first == __last)
408 iterator __next = __first;
409 while (++__next != __last)
411 if (__binary_pred(*__first, *__next))
422 __glibcxx_check_sorted(_Base::begin(), _Base::end());
423 __glibcxx_check_sorted(__x.begin().base(), __x.end().base());
424 for (iterator __tmp = __x.begin(); __tmp != __x.end(); )
426 iterator __victim = __tmp++;
427 __victim._M_attach(&__x);
429 _Base::merge(__x._M_base());
432 template<class _Compare>
434 merge(list& __x, _Compare __comp)
436 __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp);
437 __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(),
439 for (iterator __tmp = __x.begin(); __tmp != __x.end(); )
441 iterator __victim = __tmp++;
442 __victim._M_attach(&__x);
444 _Base::merge(__x._M_base(), __comp);
448 sort() { _Base::sort(); }
450 template<typename _StrictWeakOrdering>
452 sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
454 using _Base::reverse;
457 _M_base() { return *this; }
460 _M_base() const { return *this; }
466 typedef typename _Base::const_iterator _Base_const_iterator;
467 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
468 this->_M_invalidate_if(_Not_equal(_M_base().end()));
472 template<typename _Tp, typename _Alloc>
474 operator==(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
475 { return __lhs._M_base() == __rhs._M_base(); }
477 template<typename _Tp, typename _Alloc>
479 operator!=(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
480 { return __lhs._M_base() != __rhs._M_base(); }
482 template<typename _Tp, typename _Alloc>
484 operator<(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
485 { return __lhs._M_base() < __rhs._M_base(); }
487 template<typename _Tp, typename _Alloc>
489 operator<=(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
490 { return __lhs._M_base() <= __rhs._M_base(); }
492 template<typename _Tp, typename _Alloc>
494 operator>=(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
495 { return __lhs._M_base() >= __rhs._M_base(); }
497 template<typename _Tp, typename _Alloc>
499 operator>(const list<_Tp, _Alloc>& __lhs, const list<_Tp, _Alloc>& __rhs)
500 { return __lhs._M_base() > __rhs._M_base(); }
502 template<typename _Tp, typename _Alloc>
504 swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
505 { __lhs.swap(__rhs); }
506 } // namespace __debug