12 /* Forward declarations of vector and __vector_iterator */
14 template <class T, class Allocator = allocator<T>, bool BCheck = false>
17 template <class T, bool BCheck>
18 class __vector_iterator;
20 /* Normal vector iterator (not checked) */
23 class __vector_iterator<T, false>: public std::iterator<random_access_iterator_tag, T> {
25 __vector_iterator(){ ptr_ = NULL; }
26 __vector_iterator(const __vector_iterator &b){ ptr_ = b.ptr_; }
27 __vector_iterator &operator = (const __vector_iterator &b){ ptr_ = b.ptr_; return *this; }
28 __vector_iterator &operator ++ () { ++ptr_; return *this; }
29 __vector_iterator operator ++ (int) { __vector_iterator copy = *this; ++*this; return copy; }
30 __vector_iterator &operator -- () { --ptr_; return *this; }
31 __vector_iterator operator -- (int) { __vector_iterator copy = *this; --*this; return copy; }
32 __vector_iterator &operator += (ptrdiff_t n) { ptr_ += n; return *this; }
33 __vector_iterator &operator -= (ptrdiff_t n) { ptr_ -= n; return *this; }
34 __vector_iterator operator + (ptrdiff_t n) const { __vector_iterator copy = *this; copy += n; return copy; }
35 __vector_iterator operator - (ptrdiff_t n) const { __vector_iterator copy = *this; copy -= n; return copy; }
36 T &operator [] (ptrdiff_t n) const { return ptr_[n]; }
37 T &operator * () const { return *ptr_; }
41 // constructor used internally
42 __vector_iterator(const T *init_array, size_t init_size, T *init_p){ ptr_ = init_p; }
44 bool get_base_pointer() const { return false; }
46 void check() const {};
49 template <class, class, bool>
52 template <class T1, bool B1, class T2, bool B2>
53 friend bool operator == (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
54 template <class T1, bool B1, class T2, bool B2>
55 friend bool operator != (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
56 template <class T1, bool B1, class T2, bool B2>
57 friend bool operator < (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
58 template <class T1, bool B1, class T2, bool B2>
59 friend bool operator > (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
60 template <class T1, bool B1, class T2, bool B2>
61 friend bool operator <= (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
62 template <class T1, bool B1, class T2, bool B2>
63 friend bool operator >= (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
64 template <class T1, bool B1, class T2, bool B2>
65 friend ptrdiff_t operator - (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
69 /* Bounds-checked vector iterator */
72 class __vector_iterator<T, true>: public std::iterator<random_access_iterator_tag, T> {
74 __vector_iterator(){ }
75 __vector_iterator(const __vector_iterator &b){ init_ = true; array_ = b.array_; size_ = b.size_; ptr_ = b.ptr_; }
76 __vector_iterator &operator = (const __vector_iterator &b)
77 { init_ = true; invalidated_ = false; array_ = b.array_; size_ = b.size_; ptr_ = b.ptr_; return *this; }
78 __vector_iterator &operator ++ () { return *this += 1; }
79 __vector_iterator &operator -- () { return *this -= 1; }
80 __vector_iterator operator ++ (int) { __vector_iterator copy = *this; ++*this; return copy; }
81 __vector_iterator operator -- (int) { __vector_iterator copy = *this; --*this; return copy; }
82 __vector_iterator operator + (ptrdiff_t n) const { __vector_iterator copy = *this; copy += n; return copy; }
83 __vector_iterator operator - (ptrdiff_t n) const { __vector_iterator copy = *this; copy -= n; return copy; }
84 __vector_iterator &operator -= (ptrdiff_t n) { return *this += -n; }
85 T &operator [] (ptrdiff_t n) const { return *(*this + n); }
87 /* these are the only bounds-checking functions */
88 __vector_iterator &operator += (ptrdiff_t n)
91 T *new_ptr = ptr_ + n;
92 if (new_ptr < array_ || new_ptr > (array_ + size_)){
94 throw out_of_range("increment of vector iterator would exceed vector bounds");
96 throw out_of_range("decrement of vector iterator would exceed vector bounds");
103 T &operator * () const
106 if (ptr_ == array_ + size_){
107 throw out_of_range("attempt to dereference vector::end()");
114 bool invalidated_ : 1; // marked true when iterator is invalidated
115 bool init_ : 1; // initialised?
119 // constructor used internally
120 __vector_iterator(const T *init_array, size_t init_size, T *init_p)
121 { invalidated_ = false; init_ = true; array_ = init_array; size_ = init_size; ptr_ = init_p; }
123 /* throw an exception if the iterator is invalid */
127 throw logic_error("attempt to use uninitialised vector iterator");
128 } else if (invalidated_){
129 throw logic_error("attempt to use invalidated vector iterator");
133 /* mark the iterator as invalid */
134 void invalidate(){ invalidated_ = true; }
136 const T *get_base_pointer() const { return array_; }
138 template <class, class, bool>
141 template <class T1, bool B1, class T2, bool B2>
142 friend bool operator == (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
143 template <class T1, bool B1, class T2, bool B2>
144 friend bool operator != (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
145 template <class T1, bool B1, class T2, bool B2>
146 friend bool operator < (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
147 template <class T1, bool B1, class T2, bool B2>
148 friend bool operator > (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
149 template <class T1, bool B1, class T2, bool B2>
150 friend bool operator <= (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
151 template <class T1, bool B1, class T2, bool B2>
152 friend bool operator >= (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
153 template <class T1, bool B1, class T2, bool B2>
154 friend ptrdiff_t operator - (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b);
158 /* Comparisons and other operators on iterators */
160 template <class T1, bool B1, class T2, bool B2>
161 bool operator == (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
165 return a.ptr_ == b.ptr_;
168 template <class T1, bool B1, class T2, bool B2>
169 bool operator != (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
173 return a.ptr_ != b.ptr_;
176 template <class T1, bool B1, class T2, bool B2>
177 bool operator < (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
181 if (B1 && B2 && a.get_base_pointer() != b.get_base_pointer()){
182 throw out_of_range("attempt to compare vector iterators of different vectors");
184 return a.ptr_ < b.ptr_;
187 template <class T1, bool B1, class T2, bool B2>
188 bool operator > (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
192 if (B1 && B2 && a.get_base_pointer() != b.get_base_pointer()){
193 throw out_of_range("attempt to compare vector iterators of different vectors");
195 return a.ptr_ > b.ptr_;
198 template <class T1, bool B1, class T2, bool B2>
199 bool operator <= (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
203 if (B1 && B2 && a.get_base_pointer() != b.get_base_pointer()){
204 throw out_of_range("attempt to compare vector iterators of different vectors");
206 return a.ptr_ <= b.ptr_;
209 template <class T1, bool B1, class T2, bool B2>
210 bool operator >= (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
214 if (B1 && B2 && a.get_base_pointer() != b.get_base_pointer()){
215 throw out_of_range("attempt to compare vector iterators of different vectors");
217 return a.ptr_ >= b.ptr_;
220 template <class T1, bool B1, class T2, bool B2>
221 ptrdiff_t operator - (const __vector_iterator<T1, B1> &a, const __vector_iterator<T2, B2> &b)
225 if (B1 && B2 && a.get_base_pointer() != b.get_base_pointer()){
226 throw out_of_range("attempt to subtract vector iterators of different vectors");
228 return a.ptr_ - b.ptr_;
231 /* Vector implementation */
233 template <class T, class Allocator, bool BCheck>
236 typedef typename Allocator::reference reference;
237 typedef typename Allocator::const_reference const_reference;
238 typedef size_t size_type;
239 typedef ptrdiff_t difference_type;
240 typedef T value_type;
241 typedef Allocator allocator_type;
242 typedef typename Allocator::pointer pointer;
243 typedef typename Allocator::const_pointer const_pointer;
245 typedef __vector_iterator<T, BCheck> iterator;
246 typedef __vector_iterator<const T, BCheck> const_iterator;
247 typedef std::reverse_iterator<iterator> reverse_iterator;
248 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
250 explicit vector(const Allocator &new_allocator = Allocator()):
251 allocator_(new_allocator)
256 explicit vector(size_type n, const T &value = T(), const Allocator &new_allocator = Allocator()):
257 allocator_(new_allocator)
263 template <class InputIterator>
264 vector(InputIterator first, InputIterator last, const Allocator &new_allocator = Allocator()):
265 allocator_(new_allocator)
271 vector(const vector &x):
272 allocator_(x.get_allocator())
279 allocator_(x.get_allocator())
290 vector &operator = (const vector &x)
294 for (const_iterator i=x.begin(); i!=x.end(); ++i){
300 vector &operator = (vector &&x)
303 // nick x's resources
306 capacity_ = x.capacity_;
310 iterator begin(){ return iterator(array_, size_, array_); }
311 iterator end() { return iterator(array_, size_, array_ + size_); }
312 reverse_iterator rbegin(){ return reverse_iterator(end()); }
313 reverse_iterator rend(){ return reverse_iterator(begin()); }
315 const_iterator begin() const { return const_iterator(array_, size_, array_); }
316 const_iterator end() const { return const_iterator(array_, size_, array_ + size_); }
317 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
318 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
320 size_type size() const { return size_; }
321 size_type max_size() const { return allocator_.max_size(); }
322 size_type capacity() const { return capacity_; }
323 bool empty() const { return size_ == 0; }
325 void reserve(size_type n)
328 // allocate new array
329 T *new_array = allocator_.allocate(n, array_);
330 // copy all existing elements and destroy old ones
331 for (size_type i=0; i<size_; ++i){
332 allocator_.construct(new_array + i, move(array_[i]));
333 allocator_.destroy(array_ + i);
336 allocator_.deallocate(array_, capacity_);
343 void resize(size_type n, T c = T())
348 for (size_type i=size_; i<n; ++i){
349 allocator_.construct(array_ + i, c);
353 for (size_type i=n-1; i>=size_; --i){
354 allocator_.destroy(array_ + i);
360 reference operator [] (size_type n){ return *(begin() + n); }
361 const_reference operator [] (size_type n) const { return *(begin() + n); }
363 reference at(size_type n)
365 if (n >= 0 && n < size_){
368 throw out_of_range("vector index out of range");
372 const_reference at(size_type n) const
374 if (n >= 0 && n < size_){
377 throw out_of_range("vector index out of range");
381 reference front(){ return *begin(); }
382 const_reference front() const { return *begin(); }
383 reference back(){ return end()[-1]; }
384 const_reference back() const { return end()[-1]; }
387 /* Hack to fix vector::assign<int, int> ambiguity */
388 template <bool is_integer, class SuspiciousType>
391 /* version for iterator, iterator */
392 template <class InputIterator>
393 struct __assign<false, InputIterator> {
394 static void run(vector *__this, InputIterator first, InputIterator last)
396 size_t n = distance(first, last);
401 while (first != last){
402 __this->allocator_.construct(__this->array_ + i++, *first++);
408 /* version for int, int */
410 struct __assign<true, INT> {
411 static void run(vector *__this, INT n, INT u)
413 __this->assign(value_iterator<T>(u, 0), value_iterator<T>(u, n));
418 template <class SuspectType>
419 void assign(SuspectType first, SuspectType last)
421 // If InputIterator is actually an integral type, it's not an iterator.
422 // Furthermore, the call should have been to the following (size_type n, const T &u)
423 // overload, so invoke the correct specialisation of __assign (defined further down).
424 __assign<is_integral<SuspectType>::value, SuspectType>::run(this, first, last);
427 void assign(size_type n, const T &u)
429 assign(value_iterator<T>(u, 0), value_iterator<T>(u, n));
432 void push_back(const T &x)
435 allocator_.construct(array_ + size_, x);
442 allocator_.destroy(array_ + size_ - 1);
445 throw out_of_range("attempt to pop empty vector");
450 template <bool is_integer, class SuspectType> struct __insert;
451 template <class InputIterator> struct __insert<false, InputIterator> {
452 static void run(vector *__this, iterator position, InputIterator first, InputIterator last)
454 size_t off = position - __this->begin(),
455 distance = std::distance(first, last);
456 __this->shift(off, distance);
457 std::copy(first, last, __this->array_ + off);
460 template <class IntType> struct __insert<true, IntType> {
461 static void run(vector *__this, iterator position, IntType n, IntType x)
463 __insert<false, value_iterator<T> >::run(__this, position, value_iterator<T>(x, 0), value_iterator<T>(x, n));
468 iterator insert(iterator position, const T &x)
470 size_t off = position - begin();
472 allocator_.construct(array_ + off, x);
473 return begin() + off;
476 void insert(iterator position, size_type n, const T &x)
478 __insert<false, value_iterator<T> >::run(this, position, value_iterator<T>(x, 0), value_iterator<T>(x, n));
481 template <class SuspectType>
482 void insert(iterator position, SuspectType first, SuspectType last)
484 __insert<is_integral<SuspectType>::value, SuspectType>::run(this, position, first, last);
487 iterator erase(iterator position)
489 size_t off = position - begin();
491 return begin() + off;
494 iterator erase(iterator first, iterator last)
496 size_t off = first - begin();
497 unshift(off, last - first);
498 return begin() + off;
501 void swap(vector &vec)
503 std::swap(*this, vec);
509 for (i=0; i<size_; ++i){
510 allocator_.destroy(array_ + i);
515 allocator_type get_allocator() const { return allocator_; }
521 Allocator allocator_;
531 // Free all resources
535 allocator_.deallocate(array_, capacity_);
538 // Increase size, and move [pos .. end] n elements to the right
539 void shift(size_t pos, size_t n)
541 if (BCheck && pos > size_){
542 throw out_of_range("attempt to insert beyond end of vector");
545 std::move_backward(array_ + pos, array_ + size_, array_ + size_ + n);
549 // Move [pos+n .. end] n elements to the left, and reduce size
550 void unshift(size_t pos, size_t n)
552 if (BCheck && (pos + n > size_)){
553 throw out_of_range("attempt to erase beyond end of vector");
555 std::move(array_ + pos + n, array_ + size_, array_ + pos);