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