1 // Debugging deque implementation -*- C++ -*-
3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
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)
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.
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.
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/>.
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_DEQUE
30 #define _GLIBCXX_DEBUG_DEQUE 1
33 #include <debug/safe_sequence.h>
34 #include <debug/safe_iterator.h>
36 namespace std _GLIBCXX_VISIBILITY(default)
40 /// Class std::deque with safety/checking/debug instrumentation.
41 template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
43 : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>,
44 public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
46 typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base;
48 typedef typename _Base::const_iterator _Base_const_iterator;
49 typedef typename _Base::iterator _Base_iterator;
50 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
52 typedef typename _Base::reference reference;
53 typedef typename _Base::const_reference const_reference;
55 typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque>
57 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque>
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.1.1 construct/copy/destroy:
75 deque(const _Allocator& __a)
78 #if __cplusplus >= 201103L
83 deque(size_type __n, const _Tp& __value,
84 const _Allocator& __a = _Allocator())
85 : _Base(__n, __value, __a) { }
88 deque(size_type __n, const _Tp& __value = _Tp(),
89 const _Allocator& __a = _Allocator())
90 : _Base(__n, __value, __a) { }
93 #if __cplusplus >= 201103L
94 template<class _InputIterator,
95 typename = std::_RequireInputIter<_InputIterator>>
97 template<class _InputIterator>
99 deque(_InputIterator __first, _InputIterator __last,
100 const _Allocator& __a = _Allocator())
101 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
103 __gnu_debug::__base(__last), __a)
106 deque(const deque& __x)
109 deque(const _Base& __x)
112 #if __cplusplus >= 201103L
114 : _Base(std::move(__x))
115 { this->_M_swap(__x); }
117 deque(initializer_list<value_type> __l,
118 const allocator_type& __a = allocator_type())
119 : _Base(__l, __a) { }
122 ~deque() _GLIBCXX_NOEXCEPT { }
125 operator=(const deque& __x)
127 *static_cast<_Base*>(this) = __x;
128 this->_M_invalidate_all();
132 #if __cplusplus >= 201103L
134 operator=(deque&& __x) noexcept
138 __glibcxx_check_self_move_assign(__x);
145 operator=(initializer_list<value_type> __l)
147 *static_cast<_Base*>(this) = __l;
148 this->_M_invalidate_all();
153 #if __cplusplus >= 201103L
154 template<class _InputIterator,
155 typename = std::_RequireInputIter<_InputIterator>>
157 template<class _InputIterator>
160 assign(_InputIterator __first, _InputIterator __last)
162 __glibcxx_check_valid_range(__first, __last);
163 _Base::assign(__gnu_debug::__base(__first),
164 __gnu_debug::__base(__last));
165 this->_M_invalidate_all();
169 assign(size_type __n, const _Tp& __t)
171 _Base::assign(__n, __t);
172 this->_M_invalidate_all();
175 #if __cplusplus >= 201103L
177 assign(initializer_list<value_type> __l)
180 this->_M_invalidate_all();
184 using _Base::get_allocator;
188 begin() _GLIBCXX_NOEXCEPT
189 { return iterator(_Base::begin(), this); }
192 begin() const _GLIBCXX_NOEXCEPT
193 { return const_iterator(_Base::begin(), this); }
196 end() _GLIBCXX_NOEXCEPT
197 { return iterator(_Base::end(), this); }
200 end() const _GLIBCXX_NOEXCEPT
201 { return const_iterator(_Base::end(), this); }
204 rbegin() _GLIBCXX_NOEXCEPT
205 { return reverse_iterator(end()); }
207 const_reverse_iterator
208 rbegin() const _GLIBCXX_NOEXCEPT
209 { return const_reverse_iterator(end()); }
212 rend() _GLIBCXX_NOEXCEPT
213 { return reverse_iterator(begin()); }
215 const_reverse_iterator
216 rend() const _GLIBCXX_NOEXCEPT
217 { return const_reverse_iterator(begin()); }
219 #if __cplusplus >= 201103L
221 cbegin() const noexcept
222 { return const_iterator(_Base::begin(), this); }
225 cend() const noexcept
226 { return const_iterator(_Base::end(), this); }
228 const_reverse_iterator
229 crbegin() const noexcept
230 { return const_reverse_iterator(end()); }
232 const_reverse_iterator
233 crend() const noexcept
234 { return const_reverse_iterator(begin()); }
239 _M_invalidate_after_nth(difference_type __n)
241 typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
242 this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
246 // 23.2.1.2 capacity:
248 using _Base::max_size;
250 #if __cplusplus >= 201103L
252 resize(size_type __sz)
254 bool __invalidate_all = __sz > this->size();
255 if (__sz < this->size())
256 this->_M_invalidate_after_nth(__sz);
260 if (__invalidate_all)
261 this->_M_invalidate_all();
265 resize(size_type __sz, const _Tp& __c)
267 bool __invalidate_all = __sz > this->size();
268 if (__sz < this->size())
269 this->_M_invalidate_after_nth(__sz);
271 _Base::resize(__sz, __c);
273 if (__invalidate_all)
274 this->_M_invalidate_all();
278 resize(size_type __sz, _Tp __c = _Tp())
280 bool __invalidate_all = __sz > this->size();
281 if (__sz < this->size())
282 this->_M_invalidate_after_nth(__sz);
284 _Base::resize(__sz, __c);
286 if (__invalidate_all)
287 this->_M_invalidate_all();
291 #if __cplusplus >= 201103L
293 shrink_to_fit() noexcept
295 if (_Base::_M_shrink_to_fit())
296 this->_M_invalidate_all();
304 operator[](size_type __n) _GLIBCXX_NOEXCEPT
306 __glibcxx_check_subscript(__n);
307 return _M_base()[__n];
311 operator[](size_type __n) const _GLIBCXX_NOEXCEPT
313 __glibcxx_check_subscript(__n);
314 return _M_base()[__n];
320 front() _GLIBCXX_NOEXCEPT
322 __glibcxx_check_nonempty();
323 return _Base::front();
327 front() const _GLIBCXX_NOEXCEPT
329 __glibcxx_check_nonempty();
330 return _Base::front();
334 back() _GLIBCXX_NOEXCEPT
336 __glibcxx_check_nonempty();
337 return _Base::back();
341 back() const _GLIBCXX_NOEXCEPT
343 __glibcxx_check_nonempty();
344 return _Base::back();
347 // 23.2.1.3 modifiers:
349 push_front(const _Tp& __x)
351 _Base::push_front(__x);
352 this->_M_invalidate_all();
356 push_back(const _Tp& __x)
358 _Base::push_back(__x);
359 this->_M_invalidate_all();
362 #if __cplusplus >= 201103L
364 push_front(_Tp&& __x)
365 { emplace_front(std::move(__x)); }
369 { emplace_back(std::move(__x)); }
371 template<typename... _Args>
373 emplace_front(_Args&&... __args)
375 _Base::emplace_front(std::forward<_Args>(__args)...);
376 this->_M_invalidate_all();
379 template<typename... _Args>
381 emplace_back(_Args&&... __args)
383 _Base::emplace_back(std::forward<_Args>(__args)...);
384 this->_M_invalidate_all();
387 template<typename... _Args>
389 emplace(const_iterator __position, _Args&&... __args)
391 __glibcxx_check_insert(__position);
392 _Base_iterator __res = _Base::emplace(__position.base(),
393 std::forward<_Args>(__args)...);
394 this->_M_invalidate_all();
395 return iterator(__res, this);
400 #if __cplusplus >= 201103L
401 insert(const_iterator __position, const _Tp& __x)
403 insert(iterator __position, const _Tp& __x)
406 __glibcxx_check_insert(__position);
407 _Base_iterator __res = _Base::insert(__position.base(), __x);
408 this->_M_invalidate_all();
409 return iterator(__res, this);
412 #if __cplusplus >= 201103L
414 insert(const_iterator __position, _Tp&& __x)
415 { return emplace(__position, std::move(__x)); }
418 insert(const_iterator __position, initializer_list<value_type> __l)
420 __glibcxx_check_insert(__position);
421 _Base_iterator __res = _Base::insert(__position.base(), __l);
422 this->_M_invalidate_all();
423 return iterator(__res, this);
427 #if __cplusplus >= 201103L
429 insert(const_iterator __position, size_type __n, const _Tp& __x)
431 __glibcxx_check_insert(__position);
432 _Base_iterator __res = _Base::insert(__position.base(), __n, __x);
433 this->_M_invalidate_all();
434 return iterator(__res, this);
438 insert(iterator __position, size_type __n, const _Tp& __x)
440 __glibcxx_check_insert(__position);
441 _Base::insert(__position.base(), __n, __x);
442 this->_M_invalidate_all();
446 #if __cplusplus >= 201103L
447 template<class _InputIterator,
448 typename = std::_RequireInputIter<_InputIterator>>
450 insert(const_iterator __position,
451 _InputIterator __first, _InputIterator __last)
453 __glibcxx_check_insert_range(__position, __first, __last);
454 _Base_iterator __res = _Base::insert(__position.base(),
455 __gnu_debug::__base(__first),
456 __gnu_debug::__base(__last));
457 this->_M_invalidate_all();
458 return iterator(__res, this);
461 template<class _InputIterator>
463 insert(iterator __position,
464 _InputIterator __first, _InputIterator __last)
466 __glibcxx_check_insert_range(__position, __first, __last);
467 _Base::insert(__position.base(), __gnu_debug::__base(__first),
468 __gnu_debug::__base(__last));
469 this->_M_invalidate_all();
474 pop_front() _GLIBCXX_NOEXCEPT
476 __glibcxx_check_nonempty();
477 this->_M_invalidate_if(_Equal(_Base::begin()));
482 pop_back() _GLIBCXX_NOEXCEPT
484 __glibcxx_check_nonempty();
485 this->_M_invalidate_if(_Equal(--_Base::end()));
490 #if __cplusplus >= 201103L
491 erase(const_iterator __position)
493 erase(iterator __position)
496 __glibcxx_check_erase(__position);
497 #if __cplusplus >= 201103L
498 _Base_const_iterator __victim = __position.base();
500 _Base_iterator __victim = __position.base();
502 if (__victim == _Base::begin() || __victim == _Base::end() - 1)
504 this->_M_invalidate_if(_Equal(__victim));
505 return iterator(_Base::erase(__victim), this);
509 _Base_iterator __res = _Base::erase(__victim);
510 this->_M_invalidate_all();
511 return iterator(__res, this);
516 #if __cplusplus >= 201103L
517 erase(const_iterator __first, const_iterator __last)
519 erase(iterator __first, iterator __last)
522 // _GLIBCXX_RESOLVE_LIB_DEFECTS
523 // 151. can't currently clear() empty container
524 __glibcxx_check_erase_range(__first, __last);
526 if (__first.base() == __last.base())
527 #if __cplusplus >= 201103L
528 return iterator(__first.base()._M_const_cast(), this);
532 else if (__first.base() == _Base::begin()
533 || __last.base() == _Base::end())
535 this->_M_detach_singular();
536 for (_Base_const_iterator __position = __first.base();
537 __position != __last.base(); ++__position)
539 this->_M_invalidate_if(_Equal(__position));
543 return iterator(_Base::erase(__first.base(), __last.base()),
548 this->_M_revalidate_singular();
549 __throw_exception_again;
554 _Base_iterator __res = _Base::erase(__first.base(),
556 this->_M_invalidate_all();
557 return iterator(__res, this);
562 swap(deque& __x) _GLIBCXX_NOEXCEPT
569 clear() _GLIBCXX_NOEXCEPT
572 this->_M_invalidate_all();
576 _M_base() _GLIBCXX_NOEXCEPT { return *this; }
579 _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
582 template<typename _Tp, typename _Alloc>
584 operator==(const deque<_Tp, _Alloc>& __lhs,
585 const deque<_Tp, _Alloc>& __rhs)
586 { return __lhs._M_base() == __rhs._M_base(); }
588 template<typename _Tp, typename _Alloc>
590 operator!=(const deque<_Tp, _Alloc>& __lhs,
591 const deque<_Tp, _Alloc>& __rhs)
592 { return __lhs._M_base() != __rhs._M_base(); }
594 template<typename _Tp, typename _Alloc>
596 operator<(const deque<_Tp, _Alloc>& __lhs,
597 const deque<_Tp, _Alloc>& __rhs)
598 { return __lhs._M_base() < __rhs._M_base(); }
600 template<typename _Tp, typename _Alloc>
602 operator<=(const deque<_Tp, _Alloc>& __lhs,
603 const deque<_Tp, _Alloc>& __rhs)
604 { return __lhs._M_base() <= __rhs._M_base(); }
606 template<typename _Tp, typename _Alloc>
608 operator>=(const deque<_Tp, _Alloc>& __lhs,
609 const deque<_Tp, _Alloc>& __rhs)
610 { return __lhs._M_base() >= __rhs._M_base(); }
612 template<typename _Tp, typename _Alloc>
614 operator>(const deque<_Tp, _Alloc>& __lhs,
615 const deque<_Tp, _Alloc>& __rhs)
616 { return __lhs._M_base() > __rhs._M_base(); }
618 template<typename _Tp, typename _Alloc>
620 swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs)
621 { __lhs.swap(__rhs); }
623 } // namespace __debug