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