1 // Vector implementation -*- C++ -*- 2 3 // Copyright (C) 2001, 2002 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 2, 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 // You should have received a copy of the GNU General Public License along 17 // with this library; see the file COPYING. If not, write to the Free 18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19 // USA. 20 21 // As a special exception, you may use this file as part of a free software 22 // library without restriction. Specifically, if other files instantiate 23 // templates or use macros or inline functions from this file, or you compile 24 // this file and link it with other files to produce an executable, this 25 // file does not by itself cause the resulting executable to be covered by 26 // the GNU General Public License. This exception does not however 27 // invalidate any other reasons why the executable file might be covered by 28 // the GNU General Public License. 29 30 /* 31 * 32 * Copyright (c) 1994 33 * Hewlett-Packard Company 34 * 35 * Permission to use, copy, modify, distribute and sell this software 36 * and its documentation for any purpose is hereby granted without fee, 37 * provided that the above copyright notice appear in all copies and 38 * that both that copyright notice and this permission notice appear 39 * in supporting documentation. Hewlett-Packard Company makes no 40 * representations about the suitability of this software for any 41 * purpose. It is provided "as is" without express or implied warranty. 42 * 43 * 44 * Copyright (c) 1996 45 * Silicon Graphics Computer Systems, Inc. 46 * 47 * Permission to use, copy, modify, distribute and sell this software 48 * and its documentation for any purpose is hereby granted without fee, 49 * provided that the above copyright notice appear in all copies and 50 * that both that copyright notice and this permission notice appear 51 * in supporting documentation. Silicon Graphics makes no 52 * representations about the suitability of this software for any 53 * purpose. It is provided "as is" without express or implied warranty. 54 */ 55 56 /** @file stl_vector.h 57 * This is an internal header file, included by other library headers. 58 * You should not attempt to use it directly. 59 */ 60 61 #ifndef __GLIBCPP_INTERNAL_VECTOR_H 62 #define __GLIBCPP_INTERNAL_VECTOR_H 63 64 #include <bits/stl_iterator_base_funcs.h> 65 #include <bits/functexcept.h> 66 #include <bits/concept_check.h> 67 68 namespace std 69 { 70 71 // The vector base class serves two purposes. First, its constructor 72 // and destructor allocate (but don't initialize) storage. This makes 73 // exception safety easier. Second, the base class encapsulates all of 74 // the differences between SGI-style allocators and standard-conforming 75 // allocators. 76 77 // Base class for ordinary allocators. 78 template <class _Tp, class _Allocator, bool _IsStatic> 79 class _Vector_alloc_base { 80 public: 81 typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type 82 allocator_type; 83 allocator_type get_allocator() const { return _M_data_allocator; } 84 85 _Vector_alloc_base(const allocator_type& __a) 86 : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) 87 {} 88 89 protected: 90 allocator_type _M_data_allocator; 91 _Tp* _M_start; 92 _Tp* _M_finish; 93 _Tp* _M_end_of_storage; 94 95 _Tp* _M_allocate(size_t __n) 96 { return _M_data_allocator.allocate(__n); } 97 void _M_deallocate(_Tp* __p, size_t __n) 98 { if (__p) _M_data_allocator.deallocate(__p, __n); } 99 }; 100 101 // Specialization for allocators that have the property that we don't 102 // actually have to store an allocator object. 103 template <class _Tp, class _Allocator> 104 class _Vector_alloc_base<_Tp, _Allocator, true> { 105 public: 106 typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type 107 allocator_type; 108 allocator_type get_allocator() const { return allocator_type(); } 109 110 _Vector_alloc_base(const allocator_type&) 111 : _M_start(0), _M_finish(0), _M_end_of_storage(0) 112 {} 113 114 protected: 115 _Tp* _M_start; 116 _Tp* _M_finish; 117 _Tp* _M_end_of_storage; 118 119 typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; 120 _Tp* _M_allocate(size_t __n) 121 { return _Alloc_type::allocate(__n); } 122 void _M_deallocate(_Tp* __p, size_t __n) 123 { _Alloc_type::deallocate(__p, __n);} 124 }; 125 126 template <class _Tp, class _Alloc> 127 struct _Vector_base 128 : public _Vector_alloc_base<_Tp, _Alloc, 129 _Alloc_traits<_Tp, _Alloc>::_S_instanceless> 130 { 131 typedef _Vector_alloc_base<_Tp, _Alloc, 132 _Alloc_traits<_Tp, _Alloc>::_S_instanceless> 133 _Base; 134 typedef typename _Base::allocator_type allocator_type; 135 136 _Vector_base(const allocator_type& __a) : _Base(__a) {} 137 _Vector_base(size_t __n, const allocator_type& __a) : _Base(__a) { 138 _M_start = _M_allocate(__n); 139 _M_finish = _M_start; 140 _M_end_of_storage = _M_start + __n; 141 } 142 143 ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); } 144 }; 145 146 147 /** 148 * @brief A standard container which offers fixed time access to individual 149 * elements in any order. 150 * 151 * @ingroup Containers 152 * @ingroup Sequences 153 * 154 * Meets the requirements of a <a href="tables.html#65">container</a>, a 155 * <a href="tables.html#66">reversible container</a>, and a 156 * <a href="tables.html#67">sequence</a>, including the 157 * <a href="tables.html#68">optional sequence requirements</a> with the 158 * %exception of @c push_front and @c pop_front. 159 * 160 * In some terminology a vector can be described as a dynamic C-style array, 161 * it offers fast and efficient access to individual elements in any order 162 * and saves the user from worrying about memory and size allocation. 163 * Subscripting ( [] ) access is also provided as with C-style arrays. 164 */ 165 template <class _Tp, class _Alloc = allocator<_Tp> > 166 class vector : protected _Vector_base<_Tp, _Alloc> 167 { 168 // concept requirements 169 __glibcpp_class_requires(_Tp, _SGIAssignableConcept) 170 171 private: 172 typedef _Vector_base<_Tp, _Alloc> _Base; 173 typedef vector<_Tp, _Alloc> vector_type; 174 public: 175 typedef _Tp value_type; 176 typedef value_type* pointer; 177 typedef const value_type* const_pointer; 178 typedef __gnu_cxx::__normal_iterator<pointer, vector_type> iterator; 179 typedef __gnu_cxx::__normal_iterator<const_pointer, vector_type> 180 const_iterator; 181 typedef value_type& reference; 182 typedef const value_type& const_reference; 183 typedef size_t size_type; 184 typedef ptrdiff_t difference_type; 185 186 typedef typename _Base::allocator_type allocator_type; 187 allocator_type get_allocator() const { return _Base::get_allocator(); } 188 189 typedef reverse_iterator<const_iterator> const_reverse_iterator; 190 typedef reverse_iterator<iterator> reverse_iterator; 191 192 protected: 193 using _Base::_M_allocate; 194 using _Base::_M_deallocate; 195 using _Base::_M_start; 196 using _Base::_M_finish; 197 using _Base::_M_end_of_storage; 198 199 protected: 200 void _M_insert_aux(iterator __position, const _Tp& __x); 201 void _M_insert_aux(iterator __position); 202 203 public: 204 /** 205 * Returns a read/write iterator that points to the first element in the 206 * vector. Iteration is done in ordinary element order. 207 */ 208 iterator begin() { return iterator (_M_start); } 209 210 /** 211 * Returns a read-only (constant) iterator that points to the first element 212 * in the vector. Iteration is done in ordinary element order. 213 */ 214 const_iterator begin() const 215 { return const_iterator (_M_start); } 216 217 /** 218 * Returns a read/write iterator that points one past the last element in 219 * the vector. Iteration is done in ordinary element order. 220 */ 221 iterator end() { return iterator (_M_finish); } 222 223 /** 224 * Returns a read-only (constant) iterator that points one past the last 225 * element in the vector. Iteration is done in ordinary element order. 226 */ 227 const_iterator end() const { return const_iterator (_M_finish); } 228 229 /** 230 * Returns a read/write reverse iterator that points to the last element in 231 * the vector. Iteration is done in reverse element order. 232 */ 233 reverse_iterator rbegin() 234 { return reverse_iterator(end()); } 235 236 /** 237 * Returns a read-only (constant) reverse iterator that points to the last 238 * element in the vector. Iteration is done in reverse element order. 239 */ 240 const_reverse_iterator rbegin() const 241 { return const_reverse_iterator(end()); } 242 243 /** 244 * Returns a read/write reverse iterator that points to one before the 245 * first element in the vector. Iteration is done in reverse element 246 * order. 247 */ 248 reverse_iterator rend() 249 { return reverse_iterator(begin()); } 250 251 /** 252 * Returns a read-only (constant) reverse iterator that points to one 253 * before the first element in the vector. Iteration is done in reverse 254 * element order. 255 */ 256 const_reverse_iterator rend() const 257 { return const_reverse_iterator(begin()); } 258 259 /** Returns the number of elements in the vector. */ 260 size_type size() const 261 { return size_type(end() - begin()); } 262 263 /** Returns the size of the largest possible vector. */ 264 size_type max_size() const 265 { return size_type(-1) / sizeof(_Tp); } 266 267 /** 268 * Returns the amount of memory that has been alocated for the current 269 * elements (?). 270 */ 271 size_type capacity() const 272 { return size_type(const_iterator(_M_end_of_storage) - begin()); } 273 274 /** 275 * Returns true if the vector is empty. (Thus begin() would equal end().) 276 */ 277 bool empty() const 278 { return begin() == end(); } 279 280 /** 281 * @brief Subscript access to the data contained in the vector. 282 * @param n The element for which data should be accessed. 283 * @return Read/write reference to data. 284 * 285 * This operator allows for easy, array-style, data access. 286 * Note that data access with this operator is unchecked and out_of_range 287 * lookups are not defined. (For checked lookups see at().) 288 */ 289 reference operator[](size_type __n) { return *(begin() + __n); } 290 291 /** 292 * @brief Subscript access to the data contained in the vector. 293 * @param n The element for which data should be accessed. 294 * @return Read-only (constant) reference to data. 295 * 296 * This operator allows for easy, array-style, data access. 297 * Note that data access with this operator is unchecked and out_of_range 298 * lookups are not defined. (For checked lookups see at().) 299 */ 300 const_reference operator[](size_type __n) const { return *(begin() + __n); } 301 302 void _M_range_check(size_type __n) const { 303 if (__n >= this->size()) 304 __throw_out_of_range("vector"); 305 } 306 307 /** 308 * @brief Provides access to the data contained in the vector. 309 * @param n The element for which data should be accessed. 310 * @return Read/write reference to data. 311 * 312 * This function provides for safer data access. The parameter is first 313 * checked that it is in the range of the vector. The function throws 314 * out_of_range if the check fails. 315 */ 316 reference at(size_type __n) 317 { _M_range_check(__n); return (*this)[__n]; } 318 319 /** 320 * @brief Provides access to the data contained in the vector. 321 * @param n The element for which data should be accessed. 322 * @return Read-only (constant) reference to data. 323 * 324 * This function provides for safer data access. The parameter is first 325 * checked that it is in the range of the vector. The function throws 326 * out_of_range if the check fails. 327 */ 328 const_reference at(size_type __n) const 329 { _M_range_check(__n); return (*this)[__n]; } 330 331 332 explicit vector(const allocator_type& __a = allocator_type()) 333 : _Base(__a) {} 334 335 vector(size_type __n, const _Tp& __value, 336 const allocator_type& __a = allocator_type()) 337 : _Base(__n, __a) 338 { _M_finish = uninitialized_fill_n(_M_start, __n, __value); } 339 340 explicit vector(size_type __n) 341 : _Base(__n, allocator_type()) 342 { _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); } 343 344 vector(const vector<_Tp, _Alloc>& __x) 345 : _Base(__x.size(), __x.get_allocator()) 346 { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); } 347 348 // Check whether it's an integral type. If so, it's not an iterator. 349 template <class _InputIterator> 350 vector(_InputIterator __first, _InputIterator __last, 351 const allocator_type& __a = allocator_type()) 352 : _Base(__a) 353 { 354 typedef typename _Is_integer<_InputIterator>::_Integral _Integral; 355 _M_initialize_aux(__first, __last, _Integral()); 356 } 357 358 template <class _Integer> 359 void _M_initialize_aux(_Integer __n, _Integer __value, __true_type) 360 { 361 _M_start = _M_allocate(__n); 362 _M_end_of_storage = _M_start + __n; 363 _M_finish = uninitialized_fill_n(_M_start, __n, __value); 364 } 365 366 template<class _InputIterator> 367 void 368 _M_initialize_aux(_InputIterator __first, _InputIterator __last, __false_type) 369 { 370 typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory; 371 _M_range_initialize(__first, __last, _IterCategory()); 372 } 373 374 ~vector() 375 { _Destroy(_M_start, _M_finish); } 376 377 vector<_Tp, _Alloc>& operator=(const vector<_Tp, _Alloc>& __x); 378 379 /** 380 * @brief Attempt to preallocate enough memory for specified number of 381 * elements. 382 * @param n Number of elements required 383 * 384 * This function attempts to reserve enough memory for the vector to hold 385 * the specified number of elements. If the number requested is more than 386 * max_size() length_error is thrown. 387 * 388 * The advantage of this function is that if optimal code is a necessity 389 * and the user can determine the number of elements that will be required 390 * the user can reserve the memory and thus prevent a possible 391 * reallocation of memory and copy of vector data. 392 */ 393 void reserve(size_type __n) { 394 if (__n > this->max_size()) 395 __throw_length_error("vector::reserve"); 396 if (this->capacity() < __n) { 397 const size_type __old_size = size(); 398 pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish); 399 _Destroy(_M_start, _M_finish); 400 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 401 _M_start = __tmp; 402 _M_finish = __tmp + __old_size; 403 _M_end_of_storage = _M_start + __n; 404 } 405 } 406 407 // assign(), a generalized assignment member function. Two 408 // versions: one that takes a count, and one that takes a range. 409 // The range version is a member template, so we dispatch on whether 410 // or not the type is an integer. 411 412 /** 413 * @brief Assigns a given value or range to a vector. 414 * @param n Number of elements to be assigned. 415 * @param val Value to be assigned. 416 * 417 * This function can be used to assign a range to a vector or fill it 418 * with a specified number of copies of the given value. 419 * Note that the assignment completely changes the vector and that the 420 * resulting vector's size is the same as the number of elements assigned. 421 * Old data may be lost. 422 */ 423 void assign(size_type __n, const _Tp& __val) { _M_fill_assign(__n, __val); } 424 void _M_fill_assign(size_type __n, const _Tp& __val); 425 426 template<class _InputIterator> 427 void 428 assign(_InputIterator __first, _InputIterator __last) 429 { 430 typedef typename _Is_integer<_InputIterator>::_Integral _Integral; 431 _M_assign_dispatch(__first, __last, _Integral()); 432 } 433 434 template<class _Integer> 435 void 436 _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) 437 { _M_fill_assign((size_type) __n, (_Tp) __val); } 438 439 template<class _InputIter> 440 void 441 _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) 442 { 443 typedef typename iterator_traits<_InputIter>::iterator_category _IterCategory; 444 _M_assign_aux(__first, __last, _IterCategory()); 445 } 446 447 template <class _InputIterator> 448 void 449 _M_assign_aux(_InputIterator __first, _InputIterator __last, 450 input_iterator_tag); 451 452 template <class _ForwardIterator> 453 void 454 _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, 455 forward_iterator_tag); 456 457 /** 458 * Returns a read/write reference to the data at the first element of the 459 * vector. 460 */ 461 reference front() { return *begin(); } 462 463 /** 464 * Returns a read-only (constant) reference to the data at the first 465 * element of the vector. 466 */ 467 const_reference front() const { return *begin(); } 468 469 /** 470 * Returns a read/write reference to the data at the last element of the 471 * vector. 472 */ 473 reference back() { return *(end() - 1); } 474 475 /** 476 * Returns a read-only (constant) reference to the data at the first 477 * element of the vector. 478 */ 479 const_reference back() const { return *(end() - 1); } 480 481 /** 482 * @brief Add data to the end of the vector. 483 * @param x Data to be added. 484 * 485 * This is a typical stack operation. The function creates an element at 486 * the end of the vector and assigns the given data to it. 487 * Due to the nature of a vector this operation can be done in constant 488 * time if the vector has preallocated space available. 489 */ 490 void 491 push_back(const _Tp& __x) 492 { 493 if (_M_finish != _M_end_of_storage) { 494 _Construct(_M_finish, __x); 495 ++_M_finish; 496 } 497 else 498 _M_insert_aux(end(), __x); 499 } 500 501 #ifdef _GLIBCPP_DEPRECATED 502 /** 503 * Add an element to the end of the vector. The element is 504 * default-constructed. 505 * 506 * @note You must define _GLIBCPP_DEPRECATED to make this visible; see 507 * c++config.h. 508 */ 509 void 510 push_back() 511 { 512 if (_M_finish != _M_end_of_storage) { 513 _Construct(_M_finish); 514 ++_M_finish; 515 } 516 else 517 _M_insert_aux(end()); 518 } 519 #endif 520 521 void 522 swap(vector<_Tp, _Alloc>& __x) 523 { 524 std::swap(_M_start, __x._M_start); 525 std::swap(_M_finish, __x._M_finish); 526 std::swap(_M_end_of_storage, __x._M_end_of_storage); 527 } 528 529 /** 530 * @brief Inserts given value into vector at specified element. 531 * @param position An iterator that points to the element where data 532 * should be inserted. 533 * @param x Data to be inserted. 534 * @return An iterator that points to the inserted data. 535 * 536 * This function will insert the given value into the specified location. 537 * Note that this kind of operation could be expensive for a vector and if 538 * it is frequently used the user should consider using std::list. 539 */ 540 iterator 541 insert(iterator __position, const _Tp& __x) 542 { 543 size_type __n = __position - begin(); 544 if (_M_finish != _M_end_of_storage && __position == end()) { 545 _Construct(_M_finish, __x); 546 ++_M_finish; 547 } 548 else 549 _M_insert_aux(iterator(__position), __x); 550 return begin() + __n; 551 } 552 553 /** 554 * @brief Inserts an empty element into the vector. 555 * @param position An iterator that points to the element where empty 556 * element should be inserted. 557 * @param x Data to be inserted. 558 * @return An iterator that points to the inserted element. 559 * 560 * This function will insert an empty element into the specified location. 561 * Note that this kind of operation could be expensive for a vector and if 562 * it is frequently used the user should consider using std::list. 563 */ 564 iterator 565 insert(iterator __position) 566 { 567 size_type __n = __position - begin(); 568 if (_M_finish != _M_end_of_storage && __position == end()) { 569 _Construct(_M_finish); 570 ++_M_finish; 571 } 572 else 573 _M_insert_aux(iterator(__position)); 574 return begin() + __n; 575 } 576 577 // Check whether it's an integral type. If so, it's not an iterator. 578 template<class _InputIterator> 579 void 580 insert(iterator __pos, _InputIterator __first, _InputIterator __last) 581 { 582 typedef typename _Is_integer<_InputIterator>::_Integral _Integral; 583 _M_insert_dispatch(__pos, __first, __last, _Integral()); 584 } 585 586 template <class _Integer> 587 void 588 _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, __true_type) 589 { _M_fill_insert(__pos, static_cast<size_type>(__n), static_cast<_Tp>(__val)); } 590 591 template<class _InputIterator> 592 void 593 _M_insert_dispatch(iterator __pos, 594 _InputIterator __first, _InputIterator __last, 595 __false_type) 596 { 597 typedef typename iterator_traits<_InputIterator>::iterator_category _IterCategory; 598 _M_range_insert(__pos, __first, __last, _IterCategory()); 599 } 600 601 /** 602 * @brief Inserts a number of copies of given data into the vector. 603 * @param position An iterator that points to the element where data 604 * should be inserted. 605 * @param n Amount of elements to be inserted. 606 * @param x Data to be inserted. 607 * 608 * This function will insert a specified number of copies of the given data 609 * into the specified location. 610 * 611 * Note that this kind of operation could be expensive for a vector and if 612 * it is frequently used the user should consider using std::list. 613 */ 614 void insert (iterator __pos, size_type __n, const _Tp& __x) 615 { _M_fill_insert(__pos, __n, __x); } 616 617 void _M_fill_insert (iterator __pos, size_type __n, const _Tp& __x); 618 619 /** 620 * @brief Removes last element from vector. 621 * 622 * This is a typical stack operation. It allows us to shrink the vector by 623 * one. 624 * 625 * Note that no data is returned and if last element's data is needed it 626 * should be retrieved before pop_back() is called. 627 */ 628 void pop_back() { 629 --_M_finish; 630 _Destroy(_M_finish); 631 } 632 633 /** 634 * @brief Remove element at given position 635 * @param position Iterator pointing to element to be erased. 636 * @return Doc Me! (Iterator pointing to new element at old location?) 637 * 638 * This function will erase the element at the given position and thus 639 * shorten the vector by one. 640 * 641 * Note This operation could be expensive and if it is frequently used the 642 * user should consider using std::list. The user is also cautioned that 643 * this function only erases the element, and that if the element is itself 644 * a pointer, the pointed-to memory is not touched in any way. Managing 645 * the pointer is the user's responsibilty. 646 */ 647 iterator erase(iterator __position) { 648 if (__position + 1 != end()) 649 copy(__position + 1, end(), __position); 650 --_M_finish; 651 _Destroy(_M_finish); 652 return __position; 653 } 654 655 /** 656 * @brief Remove a range of elements from a vector. 657 * @param first Iterator pointing to the first element to be erased. 658 * @param last Iterator pointing to the last element to be erased. 659 * @return Doc Me! (Iterator pointing to new element at old location?) 660 * 661 * This function will erase the elements in the given range and shorten the 662 * vector accordingly. 663 * 664 * Note This operation could be expensive and if it is frequently used the 665 * user should consider using std::list. The user is also cautioned that 666 * this function only erases the elements, and that if the elements 667 * themselves are pointers, the pointed-to memory is not touched in any 668 * way. Managing the pointer is the user's responsibilty. 669 */ 670 iterator erase(iterator __first, iterator __last) { 671 iterator __i(copy(__last, end(), __first)); 672 _Destroy(__i, end()); 673 _M_finish = _M_finish - (__last - __first); 674 return __first; 675 } 676 677 /** 678 * @brief Resizes the vector to the specified number of elements. 679 * @param new_size Number of elements the vector should contain. 680 * @param x Data with which new elements should be populated. 681 * 682 * This function will resize the vector to the specified number of 683 * elements. If the number is smaller than the vector's current size the 684 * vector is truncated, otherwise the vector is extended and new elements 685 * are populated with given data. 686 */ 687 void resize(size_type __new_size, const _Tp& __x) { 688 if (__new_size < size()) 689 erase(begin() + __new_size, end()); 690 else 691 insert(end(), __new_size - size(), __x); 692 } 693 694 /** 695 * @brief Resizes the vector to the specified number of elements. 696 * @param new_size Number of elements the vector should contain. 697 * 698 * This function will resize the vector to the specified number of 699 * elements. If the number is smaller than the vector's current size the 700 * vector is truncated, otherwise the vector is extended and new elements 701 * are left uninitialized. 702 */ 703 void resize(size_type __new_size) { resize(__new_size, _Tp()); } 704 705 /** 706 * Erases all elements in vector. Note that this function only erases the 707 * elements, and that if the elements themselves are pointers, the 708 * pointed-to memory is not touched in any way. Managing the pointer is 709 * the user's responsibilty. 710 */ 711 void clear() { erase(begin(), end()); } 712 713 protected: 714 715 template <class _ForwardIterator> 716 pointer _M_allocate_and_copy(size_type __n, _ForwardIterator __first, 717 _ForwardIterator __last) 718 { 719 pointer __result = _M_allocate(__n); 720 try { 721 uninitialized_copy(__first, __last, __result); 722 return __result; 723 } 724 catch(...) 725 { 726 _M_deallocate(__result, __n); 727 __throw_exception_again; 728 } 729 } 730 731 template <class _InputIterator> 732 void _M_range_initialize(_InputIterator __first, 733 _InputIterator __last, input_iterator_tag) 734 { 735 for ( ; __first != __last; ++__first) 736 push_back(*__first); 737 } 738 739 // This function is only called by the constructor. 740 template <class _ForwardIterator> 741 void _M_range_initialize(_ForwardIterator __first, 742 _ForwardIterator __last, forward_iterator_tag) 743 { 744 size_type __n = distance(__first, __last); 745 _M_start = _M_allocate(__n); 746 _M_end_of_storage = _M_start + __n; 747 _M_finish = uninitialized_copy(__first, __last, _M_start); 748 } 749 750 template <class _InputIterator> 751 void _M_range_insert(iterator __pos, 752 _InputIterator __first, _InputIterator __last, 753 input_iterator_tag); 754 755 template <class _ForwardIterator> 756 void _M_range_insert(iterator __pos, 757 _ForwardIterator __first, _ForwardIterator __last, 758 forward_iterator_tag); 759 }; 760 761 template <class _Tp, class _Alloc> 762 inline bool 763 operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) 764 { 765 return __x.size() == __y.size() && 766 equal(__x.begin(), __x.end(), __y.begin()); 767 } 768 769 template <class _Tp, class _Alloc> 770 inline bool 771 operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) 772 { 773 return lexicographical_compare(__x.begin(), __x.end(), 774 __y.begin(), __y.end()); 775 } 776 777 template <class _Tp, class _Alloc> 778 inline void swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y) 779 { 780 __x.swap(__y); 781 } 782 783 template <class _Tp, class _Alloc> 784 inline bool 785 operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { 786 return !(__x == __y); 787 } 788 789 template <class _Tp, class _Alloc> 790 inline bool 791 operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { 792 return __y < __x; 793 } 794 795 template <class _Tp, class _Alloc> 796 inline bool 797 operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { 798 return !(__y < __x); 799 } 800 801 template <class _Tp, class _Alloc> 802 inline bool 803 operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) { 804 return !(__x < __y); 805 } 806 807 template <class _Tp, class _Alloc> 808 vector<_Tp,_Alloc>& 809 vector<_Tp,_Alloc>::operator=(const vector<_Tp, _Alloc>& __x) 810 { 811 if (&__x != this) { 812 const size_type __xlen = __x.size(); 813 if (__xlen > capacity()) { 814 pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end()); 815 _Destroy(_M_start, _M_finish); 816 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 817 _M_start = __tmp; 818 _M_end_of_storage = _M_start + __xlen; 819 } 820 else if (size() >= __xlen) { 821 iterator __i(copy(__x.begin(), __x.end(), begin())); 822 _Destroy(__i, end()); 823 } 824 else { 825 copy(__x.begin(), __x.begin() + size(), _M_start); 826 uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish); 827 } 828 _M_finish = _M_start + __xlen; 829 } 830 return *this; 831 } 832 833 template <class _Tp, class _Alloc> 834 void vector<_Tp, _Alloc>::_M_fill_assign(size_t __n, const value_type& __val) 835 { 836 if (__n > capacity()) { 837 vector<_Tp, _Alloc> __tmp(__n, __val, get_allocator()); 838 __tmp.swap(*this); 839 } 840 else if (__n > size()) { 841 fill(begin(), end(), __val); 842 _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val); 843 } 844 else 845 erase(fill_n(begin(), __n, __val), end()); 846 } 847 848 template <class _Tp, class _Alloc> template <class _InputIter> 849 void vector<_Tp, _Alloc>::_M_assign_aux(_InputIter __first, _InputIter __last, 850 input_iterator_tag) { 851 iterator __cur(begin()); 852 for ( ; __first != __last && __cur != end(); ++__cur, ++__first) 853 *__cur = *__first; 854 if (__first == __last) 855 erase(__cur, end()); 856 else 857 insert(end(), __first, __last); 858 } 859 860 template <class _Tp, class _Alloc> template <class _ForwardIter> 861 void 862 vector<_Tp, _Alloc>::_M_assign_aux(_ForwardIter __first, _ForwardIter __last, 863 forward_iterator_tag) { 864 size_type __len = distance(__first, __last); 865 866 if (__len > capacity()) { 867 pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); 868 _Destroy(_M_start, _M_finish); 869 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 870 _M_start = __tmp; 871 _M_end_of_storage = _M_finish = _M_start + __len; 872 } 873 else if (size() >= __len) { 874 iterator __new_finish(copy(__first, __last, _M_start)); 875 _Destroy(__new_finish, end()); 876 _M_finish = __new_finish.base(); 877 } 878 else { 879 _ForwardIter __mid = __first; 880 advance(__mid, size()); 881 copy(__first, __mid, _M_start); 882 _M_finish = uninitialized_copy(__mid, __last, _M_finish); 883 } 884 } 885 886 template <class _Tp, class _Alloc> 887 void 888 vector<_Tp, _Alloc>::_M_insert_aux(iterator __position, const _Tp& __x) 889 { 890 if (_M_finish != _M_end_of_storage) { 891 _Construct(_M_finish, *(_M_finish - 1)); 892 ++_M_finish; 893 _Tp __x_copy = __x; 894 copy_backward(__position, iterator(_M_finish - 2), iterator(_M_finish- 1)); 895 *__position = __x_copy; 896 } 897 else { 898 const size_type __old_size = size(); 899 const size_type __len = __old_size != 0 ? 2 * __old_size : 1; 900 iterator __new_start(_M_allocate(__len)); 901 iterator __new_finish(__new_start); 902 try { 903 __new_finish = uninitialized_copy(iterator(_M_start), __position, 904 __new_start); 905 _Construct(__new_finish.base(), __x); 906 ++__new_finish; 907 __new_finish = uninitialized_copy(__position, iterator(_M_finish), 908 __new_finish); 909 } 910 catch(...) 911 { 912 _Destroy(__new_start,__new_finish); 913 _M_deallocate(__new_start.base(),__len); 914 __throw_exception_again; 915 } 916 _Destroy(begin(), end()); 917 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 918 _M_start = __new_start.base(); 919 _M_finish = __new_finish.base(); 920 _M_end_of_storage = __new_start.base() + __len; 921 } 922 } 923 924 template <class _Tp, class _Alloc> 925 void 926 vector<_Tp, _Alloc>::_M_insert_aux(iterator __position) 927 { 928 if (_M_finish != _M_end_of_storage) { 929 _Construct(_M_finish, *(_M_finish - 1)); 930 ++_M_finish; 931 copy_backward(__position, iterator(_M_finish - 2), 932 iterator(_M_finish - 1)); 933 *__position = _Tp(); 934 } 935 else { 936 const size_type __old_size = size(); 937 const size_type __len = __old_size != 0 ? 2 * __old_size : 1; 938 pointer __new_start = _M_allocate(__len); 939 pointer __new_finish = __new_start; 940 try { 941 __new_finish = uninitialized_copy(iterator(_M_start), __position, 942 __new_start); 943 _Construct(__new_finish); 944 ++__new_finish; 945 __new_finish = uninitialized_copy(__position, iterator(_M_finish), 946 __new_finish); 947 } 948 catch(...) 949 { 950 _Destroy(__new_start,__new_finish); 951 _M_deallocate(__new_start,__len); 952 __throw_exception_again; 953 } 954 _Destroy(begin(), end()); 955 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 956 _M_start = __new_start; 957 _M_finish = __new_finish; 958 _M_end_of_storage = __new_start + __len; 959 } 960 } 961 962 template <class _Tp, class _Alloc> 963 void vector<_Tp, _Alloc>::_M_fill_insert(iterator __position, size_type __n, 964 const _Tp& __x) 965 { 966 if (__n != 0) { 967 if (size_type(_M_end_of_storage - _M_finish) >= __n) { 968 _Tp __x_copy = __x; 969 const size_type __elems_after = end() - __position; 970 iterator __old_finish(_M_finish); 971 if (__elems_after > __n) { 972 uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); 973 _M_finish += __n; 974 copy_backward(__position, __old_finish - __n, __old_finish); 975 fill(__position, __position + __n, __x_copy); 976 } 977 else { 978 uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy); 979 _M_finish += __n - __elems_after; 980 uninitialized_copy(__position, __old_finish, _M_finish); 981 _M_finish += __elems_after; 982 fill(__position, __old_finish, __x_copy); 983 } 984 } 985 else { 986 const size_type __old_size = size(); 987 const size_type __len = __old_size + max(__old_size, __n); 988 iterator __new_start(_M_allocate(__len)); 989 iterator __new_finish(__new_start); 990 try { 991 __new_finish = uninitialized_copy(begin(), __position, __new_start); 992 __new_finish = uninitialized_fill_n(__new_finish, __n, __x); 993 __new_finish 994 = uninitialized_copy(__position, end(), __new_finish); 995 } 996 catch(...) 997 { 998 _Destroy(__new_start,__new_finish); 999 _M_deallocate(__new_start.base(),__len); 1000 __throw_exception_again; 1001 } 1002 _Destroy(_M_start, _M_finish); 1003 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 1004 _M_start = __new_start.base(); 1005 _M_finish = __new_finish.base(); 1006 _M_end_of_storage = __new_start.base() + __len; 1007 } 1008 } 1009 } 1010 1011 template <class _Tp, class _Alloc> template <class _InputIterator> 1012 void 1013 vector<_Tp, _Alloc>::_M_range_insert(iterator __pos, 1014 _InputIterator __first, 1015 _InputIterator __last, 1016 input_iterator_tag) 1017 { 1018 for ( ; __first != __last; ++__first) { 1019 __pos = insert(__pos, *__first); 1020 ++__pos; 1021 } 1022 } 1023 1024 template <class _Tp, class _Alloc> template <class _ForwardIterator> 1025 void 1026 vector<_Tp, _Alloc>::_M_range_insert(iterator __position, 1027 _ForwardIterator __first, 1028 _ForwardIterator __last, 1029 forward_iterator_tag) 1030 { 1031 if (__first != __last) { 1032 size_type __n = distance(__first, __last); 1033 if (size_type(_M_end_of_storage - _M_finish) >= __n) { 1034 const size_type __elems_after = end() - __position; 1035 iterator __old_finish(_M_finish); 1036 if (__elems_after > __n) { 1037 uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); 1038 _M_finish += __n; 1039 copy_backward(__position, __old_finish - __n, __old_finish); 1040 copy(__first, __last, __position); 1041 } 1042 else { 1043 _ForwardIterator __mid = __first; 1044 advance(__mid, __elems_after); 1045 uninitialized_copy(__mid, __last, _M_finish); 1046 _M_finish += __n - __elems_after; 1047 uninitialized_copy(__position, __old_finish, _M_finish); 1048 _M_finish += __elems_after; 1049 copy(__first, __mid, __position); 1050 } 1051 } 1052 else { 1053 const size_type __old_size = size(); 1054 const size_type __len = __old_size + max(__old_size, __n); 1055 iterator __new_start(_M_allocate(__len)); 1056 iterator __new_finish(__new_start); 1057 try { 1058 __new_finish = uninitialized_copy(iterator(_M_start), 1059 __position, __new_start); 1060 __new_finish = uninitialized_copy(__first, __last, __new_finish); 1061 __new_finish 1062 = uninitialized_copy(__position, iterator(_M_finish), __new_finish); 1063 } 1064 catch(...) 1065 { 1066 _Destroy(__new_start,__new_finish); 1067 _M_deallocate(__new_start.base(), __len); 1068 __throw_exception_again; 1069 } 1070 _Destroy(_M_start, _M_finish); 1071 _M_deallocate(_M_start, _M_end_of_storage - _M_start); 1072 _M_start = __new_start.base(); 1073 _M_finish = __new_finish.base(); 1074 _M_end_of_storage = __new_start.base() + __len; 1075 } 1076 } 1077 } 1078 1079 } // namespace std 1080 1081 #endif /* __GLIBCPP_INTERNAL_VECTOR_H */ 1082 1083 // Local Variables: 1084 // mode:C++ 1085 // End: 1086