OSDN Git Service

2010-05-18 Eelis van der Weegen <gcc-bugzilla@contacts.eelis.net>
[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         // NB: DR 1204.
128         // NB: DR 675.
129         clear();
130         swap(__x);
131         return *this;
132       }
133
134       vector&
135       operator=(initializer_list<value_type> __l)
136       {
137         static_cast<_Base&>(*this) = __l;
138         this->_M_invalidate_all();
139         _M_update_guaranteed_capacity();
140         return *this;
141       }
142 #endif
143
144       template<typename _InputIterator>
145         void
146         assign(_InputIterator __first, _InputIterator __last)
147         {
148           __glibcxx_check_valid_range(__first, __last);
149           _Base::assign(__first, __last);
150           this->_M_invalidate_all();
151           _M_update_guaranteed_capacity();
152         }
153
154       void
155       assign(size_type __n, const _Tp& __u)
156       {
157         _Base::assign(__n, __u);
158         this->_M_invalidate_all();
159         _M_update_guaranteed_capacity();
160       }
161
162 #ifdef __GXX_EXPERIMENTAL_CXX0X__
163       void
164       assign(initializer_list<value_type> __l)
165       {
166         _Base::assign(__l);
167         this->_M_invalidate_all();
168         _M_update_guaranteed_capacity();
169       }
170 #endif
171
172       using _Base::get_allocator;
173
174       // iterators:
175       iterator
176       begin()
177       { return iterator(_Base::begin(), this); }
178
179       const_iterator
180       begin() const
181       { return const_iterator(_Base::begin(), this); }
182
183       iterator
184       end()
185       { return iterator(_Base::end(), this); }
186
187       const_iterator
188       end() const
189       { return const_iterator(_Base::end(), this); }
190
191       reverse_iterator
192       rbegin()
193       { return reverse_iterator(end()); }
194
195       const_reverse_iterator
196       rbegin() const
197       { return const_reverse_iterator(end()); }
198
199       reverse_iterator
200       rend()
201       { return reverse_iterator(begin()); }
202
203       const_reverse_iterator
204       rend() const
205       { return const_reverse_iterator(begin()); }
206
207 #ifdef __GXX_EXPERIMENTAL_CXX0X__
208       const_iterator
209       cbegin() const
210       { return const_iterator(_Base::begin(), this); }
211
212       const_iterator
213       cend() const
214       { return const_iterator(_Base::end(), this); }
215
216       const_reverse_iterator
217       crbegin() const
218       { return const_reverse_iterator(end()); }
219
220       const_reverse_iterator
221       crend() const
222       { return const_reverse_iterator(begin()); }
223 #endif
224
225       // 23.2.4.2 capacity:
226       using _Base::size;
227       using _Base::max_size;
228
229       void
230       resize(size_type __sz, _Tp __c = _Tp())
231       {
232         bool __realloc = _M_requires_reallocation(__sz);
233         if (__sz < this->size())
234           this->_M_invalidate_if(_After_nth(__sz, _M_base().begin()));
235         _Base::resize(__sz, __c);
236         if (__realloc)
237           this->_M_invalidate_all();
238         _M_update_guaranteed_capacity();
239       }
240
241 #ifdef __GXX_EXPERIMENTAL_CXX0X__
242       using _Base::shrink_to_fit;
243 #endif
244
245       size_type
246       capacity() const
247       {
248 #ifdef _GLIBCXX_DEBUG_PEDANTIC
249         return _M_guaranteed_capacity;
250 #else
251         return _Base::capacity();
252 #endif
253       }
254
255       using _Base::empty;
256
257       void
258       reserve(size_type __n)
259       {
260         bool __realloc = _M_requires_reallocation(__n);
261         _Base::reserve(__n);
262         if (__n > _M_guaranteed_capacity)
263           _M_guaranteed_capacity = __n;
264         if (__realloc)
265           this->_M_invalidate_all();
266       }
267
268       // element access:
269       reference
270       operator[](size_type __n)
271       {
272         __glibcxx_check_subscript(__n);
273         return _M_base()[__n];
274       }
275
276       const_reference
277       operator[](size_type __n) const
278       {
279         __glibcxx_check_subscript(__n);
280         return _M_base()[__n];
281       }
282
283       using _Base::at;
284
285       reference
286       front()
287       {
288         __glibcxx_check_nonempty();
289         return _Base::front();
290       }
291
292       const_reference
293       front() const
294       {
295         __glibcxx_check_nonempty();
296         return _Base::front();
297       }
298
299       reference
300       back()
301       {
302         __glibcxx_check_nonempty();
303         return _Base::back();
304       }
305
306       const_reference
307       back() const
308       {
309         __glibcxx_check_nonempty();
310         return _Base::back();
311       }
312
313       // _GLIBCXX_RESOLVE_LIB_DEFECTS
314       // DR 464. Suggestion for new member functions in standard containers.
315       using _Base::data;
316
317       // 23.2.4.3 modifiers:
318       void
319       push_back(const _Tp& __x)
320       {
321         bool __realloc = _M_requires_reallocation(this->size() + 1);
322         _Base::push_back(__x);
323         if (__realloc)
324           this->_M_invalidate_all();
325         _M_update_guaranteed_capacity();
326       }
327
328 #ifdef __GXX_EXPERIMENTAL_CXX0X__
329       template<typename _Up = _Tp>
330         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
331                                         void>::__type
332         push_back(_Tp&& __x)
333         { emplace_back(std::move(__x)); }
334
335       template<typename... _Args>
336         void
337         emplace_back(_Args&&... __args)
338         {
339           bool __realloc = _M_requires_reallocation(this->size() + 1);
340           _Base::emplace_back(std::forward<_Args>(__args)...);
341           if (__realloc)
342             this->_M_invalidate_all();
343           _M_update_guaranteed_capacity();
344         }
345 #endif
346
347       void
348       pop_back()
349       {
350         __glibcxx_check_nonempty();
351         iterator __victim = end() - 1;
352         __victim._M_invalidate();
353         _Base::pop_back();
354       }
355
356 #ifdef __GXX_EXPERIMENTAL_CXX0X__
357       template<typename... _Args>
358         iterator
359         emplace(iterator __position, _Args&&... __args)
360         {
361           __glibcxx_check_insert(__position);
362           bool __realloc = _M_requires_reallocation(this->size() + 1);
363           difference_type __offset = __position - begin();
364           typename _Base::iterator __res = _Base::emplace(__position.base(),
365                                             std::forward<_Args>(__args)...);
366           if (__realloc)
367             this->_M_invalidate_all();
368           else
369             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
370           _M_update_guaranteed_capacity();
371           return iterator(__res, this);
372         }
373 #endif
374
375       iterator
376       insert(iterator __position, const _Tp& __x)
377       {
378         __glibcxx_check_insert(__position);
379         bool __realloc = _M_requires_reallocation(this->size() + 1);
380         difference_type __offset = __position - begin();
381         typename _Base::iterator __res = _Base::insert(__position.base(),__x);
382         if (__realloc)
383           this->_M_invalidate_all();
384         else
385           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
386         _M_update_guaranteed_capacity();
387         return iterator(__res, this);
388       }
389
390 #ifdef __GXX_EXPERIMENTAL_CXX0X__
391       template<typename _Up = _Tp>
392         typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value,
393                                         iterator>::__type
394         insert(iterator __position, _Tp&& __x)
395         { return emplace(__position, std::move(__x)); }
396
397       void
398       insert(iterator __position, initializer_list<value_type> __l)
399       { this->insert(__position, __l.begin(), __l.end()); }
400 #endif
401
402       void
403       insert(iterator __position, size_type __n, const _Tp& __x)
404       {
405         __glibcxx_check_insert(__position);
406         bool __realloc = _M_requires_reallocation(this->size() + __n);
407         difference_type __offset = __position - begin();
408         _Base::insert(__position.base(), __n, __x);
409         if (__realloc)
410           this->_M_invalidate_all();
411         else
412           this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
413         _M_update_guaranteed_capacity();
414       }
415
416       template<class _InputIterator>
417         void
418         insert(iterator __position,
419                _InputIterator __first, _InputIterator __last)
420         {
421           __glibcxx_check_insert_range(__position, __first, __last);
422
423           /* Hard to guess if invalidation will occur, because __last
424              - __first can't be calculated in all cases, so we just
425              punt here by checking if it did occur. */
426           typename _Base::iterator __old_begin = _M_base().begin();
427           difference_type __offset = __position - begin();
428           _Base::insert(__position.base(), __first, __last);
429
430           if (_M_base().begin() != __old_begin)
431             this->_M_invalidate_all();
432           else
433             this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
434           _M_update_guaranteed_capacity();
435         }
436
437       iterator
438       erase(iterator __position)
439       {
440         __glibcxx_check_erase(__position);
441         difference_type __offset = __position - begin();
442         typename _Base::iterator __res = _Base::erase(__position.base());
443         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
444         return iterator(__res, this);
445       }
446
447       iterator
448       erase(iterator __first, iterator __last)
449       {
450         // _GLIBCXX_RESOLVE_LIB_DEFECTS
451         // 151. can't currently clear() empty container
452         __glibcxx_check_erase_range(__first, __last);
453
454         difference_type __offset = __first - begin();
455         typename _Base::iterator __res = _Base::erase(__first.base(),
456                                                          __last.base());
457         this->_M_invalidate_if(_After_nth(__offset, _M_base().begin()));
458         return iterator(__res, this);
459       }
460
461       void
462       swap(vector& __x)
463       {
464         _Base::swap(__x);
465         this->_M_swap(__x);
466         std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
467       }
468
469       void
470       clear()
471       {
472         _Base::clear();
473         this->_M_invalidate_all();
474         _M_guaranteed_capacity = 0;
475       }
476
477       _Base&
478       _M_base() { return *this; }
479
480       const _Base&
481       _M_base() const { return *this; }
482
483     private:
484       size_type _M_guaranteed_capacity;
485
486       bool
487       _M_requires_reallocation(size_type __elements)
488       { return __elements > this->capacity(); }
489
490       void
491       _M_update_guaranteed_capacity()
492       {
493         if (this->size() > _M_guaranteed_capacity)
494           _M_guaranteed_capacity = this->size();
495       }
496     };
497
498   template<typename _Tp, typename _Alloc>
499     inline bool
500     operator==(const vector<_Tp, _Alloc>& __lhs,
501                const vector<_Tp, _Alloc>& __rhs)
502     { return __lhs._M_base() == __rhs._M_base(); }
503
504   template<typename _Tp, typename _Alloc>
505     inline bool
506     operator!=(const vector<_Tp, _Alloc>& __lhs,
507                const vector<_Tp, _Alloc>& __rhs)
508     { return __lhs._M_base() != __rhs._M_base(); }
509
510   template<typename _Tp, typename _Alloc>
511     inline bool
512     operator<(const vector<_Tp, _Alloc>& __lhs,
513               const vector<_Tp, _Alloc>& __rhs)
514     { return __lhs._M_base() < __rhs._M_base(); }
515
516   template<typename _Tp, typename _Alloc>
517     inline bool
518     operator<=(const vector<_Tp, _Alloc>& __lhs,
519                const vector<_Tp, _Alloc>& __rhs)
520     { return __lhs._M_base() <= __rhs._M_base(); }
521
522   template<typename _Tp, typename _Alloc>
523     inline bool
524     operator>=(const vector<_Tp, _Alloc>& __lhs,
525                const vector<_Tp, _Alloc>& __rhs)
526     { return __lhs._M_base() >= __rhs._M_base(); }
527
528   template<typename _Tp, typename _Alloc>
529     inline bool
530     operator>(const vector<_Tp, _Alloc>& __lhs,
531               const vector<_Tp, _Alloc>& __rhs)
532     { return __lhs._M_base() > __rhs._M_base(); }
533
534   template<typename _Tp, typename _Alloc>
535     inline void
536     swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
537     { __lhs.swap(__rhs); }
538
539 } // namespace __debug
540
541 #ifdef __GXX_EXPERIMENTAL_CXX0X__
542   // DR 1182.
543   /// std::hash specialization for vector<bool>.
544   template<typename _Alloc>
545     struct hash<__debug::vector<bool, _Alloc>>
546     : public std::unary_function<__debug::vector<bool, _Alloc>, size_t>
547     {
548       size_t
549       operator()(const __debug::vector<bool, _Alloc>& __b) const
550       { return std::hash<_GLIBCXX_STD_D::vector<bool, _Alloc>>()
551           (__b._M_base()); }
552     };
553 #endif
554
555 } // namespace std
556
557 #endif