OSDN Git Service

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