xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/debug/deque (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1// Debugging deque 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/deque
27 *  This file is a GNU debug extension to the Standard C++ Library.
28 */
29
30#ifndef _GLIBCXX_DEBUG_DEQUE
31#define _GLIBCXX_DEBUG_DEQUE 1
32
33#include <deque>
34#include <debug/safe_sequence.h>
35#include <debug/safe_iterator.h>
36
37namespace std
38{
39namespace __debug
40{
41  /// Class std::deque with safety/checking/debug instrumentation.
42  template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
43    class deque
44    : public _GLIBCXX_STD_D::deque<_Tp, _Allocator>,
45      public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
46    {
47      typedef  _GLIBCXX_STD_D::deque<_Tp, _Allocator> _Base;
48      typedef __gnu_debug::_Safe_sequence<deque> _Safe_base;
49
50    public:
51      typedef typename _Base::reference             reference;
52      typedef typename _Base::const_reference       const_reference;
53
54      typedef __gnu_debug::_Safe_iterator<typename _Base::iterator,deque>
55						    iterator;
56      typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,deque>
57						     const_iterator;
58
59      typedef typename _Base::size_type             size_type;
60      typedef typename _Base::difference_type       difference_type;
61
62      typedef _Tp				    value_type;
63      typedef _Allocator			    allocator_type;
64      typedef typename _Base::pointer               pointer;
65      typedef typename _Base::const_pointer         const_pointer;
66      typedef std::reverse_iterator<iterator>       reverse_iterator;
67      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
68
69      // 23.2.1.1 construct/copy/destroy:
70      explicit deque(const _Allocator& __a = _Allocator())
71      : _Base(__a) { }
72
73      explicit deque(size_type __n, const _Tp& __value = _Tp(),
74		     const _Allocator& __a = _Allocator())
75      : _Base(__n, __value, __a) { }
76
77      template<class _InputIterator>
78        deque(_InputIterator __first, _InputIterator __last,
79	      const _Allocator& __a = _Allocator())
80	: _Base(__gnu_debug::__check_valid_range(__first, __last), __last, __a)
81        { }
82
83      deque(const deque& __x)
84      : _Base(__x), _Safe_base() { }
85
86      deque(const _Base& __x)
87      : _Base(__x), _Safe_base() { }
88
89#ifdef __GXX_EXPERIMENTAL_CXX0X__
90      deque(deque&& __x)
91      : _Base(std::forward<deque>(__x)), _Safe_base()
92      { this->_M_swap(__x); }
93
94      deque(initializer_list<value_type> __l,
95	    const allocator_type& __a = allocator_type())
96      : _Base(__l, __a), _Safe_base() { }
97#endif
98
99      ~deque() { }
100
101      deque&
102      operator=(const deque& __x)
103      {
104	*static_cast<_Base*>(this) = __x;
105	this->_M_invalidate_all();
106	return *this;
107      }
108
109#ifdef __GXX_EXPERIMENTAL_CXX0X__
110      deque&
111      operator=(deque&& __x)
112      {
113	// NB: DR 1204.
114	// NB: DR 675.
115	clear();
116	swap(__x);
117	return *this;
118      }
119
120      deque&
121      operator=(initializer_list<value_type> __l)
122      {
123	*static_cast<_Base*>(this) = __l;
124	this->_M_invalidate_all();
125	return *this;
126      }
127#endif
128
129      template<class _InputIterator>
130        void
131        assign(_InputIterator __first, _InputIterator __last)
132        {
133	  __glibcxx_check_valid_range(__first, __last);
134	  _Base::assign(__first, __last);
135	  this->_M_invalidate_all();
136	}
137
138      void
139      assign(size_type __n, const _Tp& __t)
140      {
141	_Base::assign(__n, __t);
142	this->_M_invalidate_all();
143      }
144
145#ifdef __GXX_EXPERIMENTAL_CXX0X__
146      void
147      assign(initializer_list<value_type> __l)
148      {
149	_Base::assign(__l);
150	this->_M_invalidate_all();
151      }
152#endif
153
154      using _Base::get_allocator;
155
156      // iterators:
157      iterator
158      begin()
159      { return iterator(_Base::begin(), this); }
160
161      const_iterator
162      begin() const
163      { return const_iterator(_Base::begin(), this); }
164
165      iterator
166      end()
167      { return iterator(_Base::end(), this); }
168
169      const_iterator
170      end() const
171      { return const_iterator(_Base::end(), this); }
172
173      reverse_iterator
174      rbegin()
175      { return reverse_iterator(end()); }
176
177      const_reverse_iterator
178      rbegin() const
179      { return const_reverse_iterator(end()); }
180
181      reverse_iterator
182      rend()
183      { return reverse_iterator(begin()); }
184
185      const_reverse_iterator
186      rend() const
187      { return const_reverse_iterator(begin()); }
188
189#ifdef __GXX_EXPERIMENTAL_CXX0X__
190      const_iterator
191      cbegin() const
192      { return const_iterator(_Base::begin(), this); }
193
194      const_iterator
195      cend() const
196      { return const_iterator(_Base::end(), this); }
197
198      const_reverse_iterator
199      crbegin() const
200      { return const_reverse_iterator(end()); }
201
202      const_reverse_iterator
203      crend() const
204      { return const_reverse_iterator(begin()); }
205#endif
206
207      // 23.2.1.2 capacity:
208      using _Base::size;
209      using _Base::max_size;
210
211      void
212      resize(size_type __sz, _Tp __c = _Tp())
213      {
214	typedef typename _Base::const_iterator _Base_const_iterator;
215	typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
216
217	bool __invalidate_all = __sz > this->size();
218	if (__sz < this->size())
219	  this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
220
221	_Base::resize(__sz, __c);
222
223	if (__invalidate_all)
224	  this->_M_invalidate_all();
225      }
226
227#ifdef __GXX_EXPERIMENTAL_CXX0X__
228      using _Base::shrink_to_fit;
229#endif
230
231      using _Base::empty;
232
233      // element access:
234      reference
235      operator[](size_type __n)
236      {
237	__glibcxx_check_subscript(__n);
238	return _M_base()[__n];
239      }
240
241      const_reference
242      operator[](size_type __n) const
243      {
244	__glibcxx_check_subscript(__n);
245	return _M_base()[__n];
246      }
247
248      using _Base::at;
249
250      reference
251      front()
252      {
253	__glibcxx_check_nonempty();
254	return _Base::front();
255      }
256
257      const_reference
258      front() const
259      {
260	__glibcxx_check_nonempty();
261	return _Base::front();
262      }
263
264      reference
265      back()
266      {
267	__glibcxx_check_nonempty();
268	return _Base::back();
269      }
270
271      const_reference
272      back() const
273      {
274	__glibcxx_check_nonempty();
275	return _Base::back();
276      }
277
278      // 23.2.1.3 modifiers:
279      void
280      push_front(const _Tp& __x)
281      {
282	_Base::push_front(__x);
283	this->_M_invalidate_all();
284      }
285
286      void
287      push_back(const _Tp& __x)
288      {
289	_Base::push_back(__x);
290	this->_M_invalidate_all();
291      }
292
293#ifdef __GXX_EXPERIMENTAL_CXX0X__
294      void
295      push_front(_Tp&& __x)
296      { emplace_front(std::move(__x)); }
297
298      void
299      push_back(_Tp&& __x)
300      { emplace_back(std::move(__x)); }
301
302      template<typename... _Args>
303        void
304        emplace_front(_Args&&... __args)
305	{
306	  _Base::emplace_front(std::forward<_Args>(__args)...);
307	  this->_M_invalidate_all();
308	}
309
310      template<typename... _Args>
311        void
312        emplace_back(_Args&&... __args)
313	{
314	  _Base::emplace_back(std::forward<_Args>(__args)...);
315	  this->_M_invalidate_all();
316	}
317
318      template<typename... _Args>
319        iterator
320        emplace(iterator __position, _Args&&... __args)
321	{
322	  __glibcxx_check_insert(__position);
323	  typename _Base::iterator __res = _Base::emplace(__position.base(),
324					    std::forward<_Args>(__args)...);
325	  this->_M_invalidate_all();
326	  return iterator(__res, this);
327	}
328#endif
329
330      iterator
331      insert(iterator __position, const _Tp& __x)
332      {
333	__glibcxx_check_insert(__position);
334	typename _Base::iterator __res = _Base::insert(__position.base(), __x);
335	this->_M_invalidate_all();
336	return iterator(__res, this);
337      }
338
339#ifdef __GXX_EXPERIMENTAL_CXX0X__
340      iterator
341      insert(iterator __position, _Tp&& __x)
342      { return emplace(__position, std::move(__x)); }
343
344      void
345      insert(iterator __p, initializer_list<value_type> __l)
346      {
347	_Base::insert(__p, __l);
348	this->_M_invalidate_all();
349      }
350#endif
351
352      void
353      insert(iterator __position, size_type __n, const _Tp& __x)
354      {
355	__glibcxx_check_insert(__position);
356	_Base::insert(__position.base(), __n, __x);
357	this->_M_invalidate_all();
358      }
359
360      template<class _InputIterator>
361        void
362        insert(iterator __position,
363	       _InputIterator __first, _InputIterator __last)
364        {
365	  __glibcxx_check_insert_range(__position, __first, __last);
366	  _Base::insert(__position.base(), __first, __last);
367	  this->_M_invalidate_all();
368	}
369
370      void
371      pop_front()
372      {
373	__glibcxx_check_nonempty();
374	iterator __victim = begin();
375	__victim._M_invalidate();
376	_Base::pop_front();
377      }
378
379      void
380      pop_back()
381      {
382	__glibcxx_check_nonempty();
383	iterator __victim = end();
384	--__victim;
385	__victim._M_invalidate();
386	_Base::pop_back();
387      }
388
389      iterator
390      erase(iterator __position)
391      {
392	__glibcxx_check_erase(__position);
393	if (__position == begin() || __position == end()-1)
394	  {
395	    __position._M_invalidate();
396	    return iterator(_Base::erase(__position.base()), this);
397	  }
398	else
399	  {
400	    typename _Base::iterator __res = _Base::erase(__position.base());
401	    this->_M_invalidate_all();
402	    return iterator(__res, this);
403	  }
404      }
405
406      iterator
407      erase(iterator __first, iterator __last)
408      {
409	// _GLIBCXX_RESOLVE_LIB_DEFECTS
410	// 151. can't currently clear() empty container
411	__glibcxx_check_erase_range(__first, __last);
412        if (__first == begin() || __last == end())
413	  {
414	    this->_M_detach_singular();
415	    for (iterator __position = __first; __position != __last; )
416	      {
417		iterator __victim = __position++;
418		__victim._M_invalidate();
419	      }
420	    __try
421	      {
422		return iterator(_Base::erase(__first.base(), __last.base()),
423				this);
424	      }
425	    __catch(...)
426	      {
427		this->_M_revalidate_singular();
428		__throw_exception_again;
429	      }
430	  }
431	else
432	  {
433	    typename _Base::iterator __res = _Base::erase(__first.base(),
434							  __last.base());
435	    this->_M_invalidate_all();
436	    return iterator(__res, this);
437	  }
438      }
439
440      void
441      swap(deque& __x)
442      {
443	_Base::swap(__x);
444	this->_M_swap(__x);
445      }
446
447      void
448      clear()
449      {
450	_Base::clear();
451	this->_M_invalidate_all();
452      }
453
454      _Base&
455      _M_base()       { return *this; }
456
457      const _Base&
458      _M_base() const { return *this; }
459    };
460
461  template<typename _Tp, typename _Alloc>
462    inline bool
463    operator==(const deque<_Tp, _Alloc>& __lhs,
464	       const deque<_Tp, _Alloc>& __rhs)
465    { return __lhs._M_base() == __rhs._M_base(); }
466
467  template<typename _Tp, typename _Alloc>
468    inline bool
469    operator!=(const deque<_Tp, _Alloc>& __lhs,
470	       const deque<_Tp, _Alloc>& __rhs)
471    { return __lhs._M_base() != __rhs._M_base(); }
472
473  template<typename _Tp, typename _Alloc>
474    inline bool
475    operator<(const deque<_Tp, _Alloc>& __lhs,
476	      const deque<_Tp, _Alloc>& __rhs)
477    { return __lhs._M_base() < __rhs._M_base(); }
478
479  template<typename _Tp, typename _Alloc>
480    inline bool
481    operator<=(const deque<_Tp, _Alloc>& __lhs,
482	       const deque<_Tp, _Alloc>& __rhs)
483    { return __lhs._M_base() <= __rhs._M_base(); }
484
485  template<typename _Tp, typename _Alloc>
486    inline bool
487    operator>=(const deque<_Tp, _Alloc>& __lhs,
488	       const deque<_Tp, _Alloc>& __rhs)
489    { return __lhs._M_base() >= __rhs._M_base(); }
490
491  template<typename _Tp, typename _Alloc>
492    inline bool
493    operator>(const deque<_Tp, _Alloc>& __lhs,
494	      const deque<_Tp, _Alloc>& __rhs)
495    { return __lhs._M_base() > __rhs._M_base(); }
496
497  template<typename _Tp, typename _Alloc>
498    inline void
499    swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs)
500    { __lhs.swap(__rhs); }
501
502} // namespace __debug
503} // namespace std
504
505#endif
506