MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
vector.hpp
1#ifndef MSTL_CORE_CONTAINER_VECTOR_HPP__
2#define MSTL_CORE_CONTAINER_VECTOR_HPP__
9
10template <bool IsConst, typename Vector>
11struct vector_iterator {
12private:
13 using iterator = vector_iterator<false, Vector>;
14 using const_iterator = vector_iterator<true, Vector>;
15
16public:
17 using iterator_category = contiguous_iterator_tag;
18 using value_type = typename Vector::value_type;
21 using difference_type = typename Vector::difference_type;
22 using size_type = typename Vector::size_type;
23
24private:
25 pointer ptr_ = nullptr;
26 const Vector* vec_ = nullptr;
27
28 template <bool, typename> friend struct vector_iterator;
29 template <typename, typename> friend class vector;
30
31public:
32 MSTL_CONSTEXPR20 vector_iterator() = default;
33 MSTL_CONSTEXPR20 vector_iterator(pointer ptr, const Vector* vec) : ptr_(ptr), vec_(vec) {}
34
35 MSTL_CONSTEXPR20 vector_iterator(const iterator& x) noexcept
36 : ptr_(const_cast<pointer>(x.ptr_)), vec_(x.vec_) {}
37
38 MSTL_CONSTEXPR20 vector_iterator& operator =(const iterator& rhs) noexcept {
39 if (_MSTL addressof(rhs) == this) return *this;
40 ptr_ = const_cast<pointer>(rhs.ptr_);
41 vec_ = rhs.vec_;
42 return *this;
43 }
44
45 MSTL_CONSTEXPR20 vector_iterator(iterator&& x) noexcept
46 : ptr_(const_cast<pointer>(x.ptr_)), vec_(x.vec_) {
47 x.ptr_ = nullptr;
48 x.vec_ = nullptr;
49 }
50
51 MSTL_CONSTEXPR20 vector_iterator& operator =(iterator&& rhs) noexcept {
52 if (_MSTL addressof(rhs) == this) return *this;
53 ptr_ = const_cast<pointer>(rhs.ptr_);
54 vec_ = rhs.vec_;
55 rhs.ptr_ = nullptr;
56 rhs.vec_ = nullptr;
57 return *this;
58 }
59
60 MSTL_CONSTEXPR20 vector_iterator(const const_iterator& x) noexcept
61 : ptr_(const_cast<pointer>(x.ptr_)), vec_(x.vec_) {}
62
63 MSTL_CONSTEXPR20 vector_iterator& operator =(const const_iterator& rhs) noexcept {
64 if (_MSTL addressof(rhs) == this) return *this;
65 ptr_ = const_cast<pointer>(rhs.ptr_);
66 vec_ = rhs.vec_;
67 return *this;
68 }
69
70 MSTL_CONSTEXPR20 vector_iterator(const_iterator&& x) noexcept
71 : ptr_(const_cast<pointer>(x.ptr_)), vec_(x.vec_) {
72 x.ptr_ = nullptr;
73 x.vec_ = nullptr;
74 }
75
76 MSTL_CONSTEXPR20 vector_iterator& operator =(const_iterator&& rhs) noexcept {
77 if (_MSTL addressof(rhs) == this) return *this;
78 ptr_ = const_cast<pointer>(rhs.ptr_);
79 vec_ = rhs.vec_;
80 rhs.ptr_ = nullptr;
81 rhs.vec_ = nullptr;
82 return *this;
83 }
84
85 MSTL_CONSTEXPR20 ~vector_iterator() noexcept = default;
86
87 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator *() const noexcept {
88 MSTL_DEBUG_VERIFY(ptr_ && vec_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(vector_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
89 MSTL_DEBUG_VERIFY(vec_->start_ <= ptr_ && ptr_ <= vec_->finish_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(vector_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
90 return *ptr_;
91 }
92
93 MSTL_NODISCARD MSTL_CONSTEXPR20 pointer operator ->() const noexcept {
94 return &operator*();
95 }
96
97 MSTL_CONSTEXPR20 vector_iterator& operator ++() noexcept {
98 MSTL_DEBUG_VERIFY(ptr_ && vec_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(vector_iterator, __MSTL_DEBUG_TAG_INCREMENT));
99 MSTL_DEBUG_VERIFY(ptr_ < vec_->finish_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(vector_iterator, __MSTL_DEBUG_TAG_INCREMENT));
100 ++ptr_;
101 return *this;
102 }
103
104 MSTL_CONSTEXPR20 vector_iterator operator ++(int) noexcept {
105 vector_iterator temp = *this;
106 ++*this;
107 return temp;
108 }
109
110 MSTL_CONSTEXPR20 vector_iterator& operator --() noexcept {
111 MSTL_DEBUG_VERIFY(ptr_ && vec_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(vector_iterator, __MSTL_DEBUG_TAG_DECREMENT));
112 MSTL_DEBUG_VERIFY(vec_->start_ < ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(vector_iterator, __MSTL_DEBUG_TAG_DECREMENT));
113 --ptr_;
114 return *this;
115 }
116
117 MSTL_CONSTEXPR20 vector_iterator operator --(int) noexcept {
118 vector_iterator temp = *this;
119 --*this;
120 return temp;
121 }
122
123 MSTL_CONSTEXPR20 vector_iterator& operator +=(difference_type n) noexcept {
124 if (n < 0) {
125 MSTL_DEBUG_VERIFY((ptr_ && vec_) || n == 0, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(vector_iterator, __MSTL_DEBUG_TAG_DECREMENT));
126 MSTL_DEBUG_VERIFY(n >= vec_->start_ - ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(vector_iterator, __MSTL_DEBUG_TAG_DECREMENT));
127 }
128 else if (n > 0) {
129 MSTL_DEBUG_VERIFY((ptr_ && vec_) || n == 0, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(vector_iterator, __MSTL_DEBUG_TAG_INCREMENT));
130 MSTL_DEBUG_VERIFY(n <= vec_->finish_ - ptr_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(vector_iterator, __MSTL_DEBUG_TAG_INCREMENT));
131 }
132 ptr_ += n;
133 return *this;
134 }
135
136 MSTL_NODISCARD MSTL_CONSTEXPR20 vector_iterator operator +(difference_type n) const noexcept {
137 auto tmp = *this;
138 tmp += n;
139 return tmp;
140 }
141
142 MSTL_NODISCARD friend MSTL_CONSTEXPR20 vector_iterator operator +(difference_type n, const vector_iterator& it) {
143 return it + n;
144 }
145
146 MSTL_CONSTEXPR20 vector_iterator& operator -=(difference_type n) noexcept {
147 ptr_ += -n;
148 return *this;
149 }
150
151 MSTL_NODISCARD MSTL_CONSTEXPR20 vector_iterator operator -(difference_type n) const noexcept {
152 auto tmp = *this;
153 tmp -= n;
154 return tmp;
155 }
156
157 MSTL_NODISCARD MSTL_CONSTEXPR20 difference_type operator -(const vector_iterator& x) const noexcept {
158 MSTL_DEBUG_VERIFY(vec_ == x.vec_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
159 return static_cast<difference_type>(ptr_ - x.ptr_);
160 }
161
162 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator [](difference_type n) noexcept {
163 return *(*this + n);
164 }
165
166 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(const vector_iterator& x) const noexcept {
167 MSTL_DEBUG_VERIFY(vec_ == x.vec_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
168 return ptr_ == x.ptr_;
169 }
170 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator !=(const vector_iterator& x) const noexcept {
171 return !(*this == x);
172 }
173 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(const vector_iterator& x) const noexcept {
174 MSTL_DEBUG_VERIFY(vec_ == x.vec_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(vector_iterator));
175 return ptr_ < x.ptr_;
176 }
177 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >(const vector_iterator& x) const noexcept {
178 return x < *this;
179 }
180 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <=(const vector_iterator& x) const noexcept {
181 return !(*this > x);
182 }
183 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator >=(const vector_iterator& x) const noexcept {
184 return !(*this < x);
185 }
186
187 MSTL_NODISCARD constexpr pointer base() const noexcept {
188 return ptr_;
189 }
190};
191
192template <typename T, typename Alloc = allocator<T>>
193class vector : public icollector<vector<T, Alloc>> {
194#ifdef MSTL_STANDARD_20__
195 static_assert(is_allocator_v<Alloc>, "Alloc type is not a standard allocator type.");
196#endif
197 static_assert(is_same_v<T, typename Alloc::value_type>, "allocator type mismatch.");
198 static_assert(is_object_v<T>, "vector only contains object types.");
199
200public:
202 using iterator = vector_iterator<false, vector<T, Alloc>>;
203 using const_iterator = vector_iterator<true, vector<T, Alloc>>;
204 using reverse_iterator = _MSTL reverse_iterator<iterator>;
205 using const_reverse_iterator = _MSTL reverse_iterator<const_iterator>;
206 using allocator_type = Alloc;
207
208private:
209 pointer start_ = nullptr;
210 pointer finish_ = nullptr;
211 compressed_pair<allocator_type, pointer> pair_{ default_construct_tag{}, nullptr };
212
213 template <bool, typename> friend struct vector_iterator;
214
215private:
216 MSTL_CONSTEXPR20 void fill_initialize(size_type n, const T& x) {
217 start_ = pair_.get_base().allocate(n);
218 _MSTL uninitialized_fill_n(start_, n, x);
219 finish_ = start_ + n;
220 pair_.value = finish_;
221 }
222
223 template <typename Iterator>
224 MSTL_CONSTEXPR20 pointer allocate_and_copy(size_type n, Iterator first, Iterator last) {
225 pointer result = pair_.get_base().allocate(n);
226 pointer finish = result;
227 try {
228 finish = _MSTL uninitialized_copy(first, last, result);
229 } catch (...) {
230 _MSTL destroy(result, finish);
231 pair_.get_base().deallocate(result, n);
232 throw;
233 }
234 return result;
235 }
236
237 template <typename Iterator>
238 MSTL_CONSTEXPR20 pointer allocate_and_move(size_type n, Iterator first, Iterator last) {
239 pointer result = pair_.get_base().allocate(n);
240 pointer finish = result;
241 try {
242 finish = _MSTL uninitialized_move(first, last, result);
243 } catch (...) {
244 _MSTL destroy(result, finish);
245 pair_.get_base().deallocate(result, n);
246 throw;
247 }
248 return result;
249 }
250
251 template <typename Iterator, enable_if_t<
253 MSTL_CONSTEXPR20 void range_initialize(Iterator first, Iterator last) {
254 for (; first != last; ++first)
255 this->push_back(*first);
256 }
257
258 template <typename Iterator, enable_if_t<is_ranges_fwd_iter_v<Iterator>, int> = 0>
259 MSTL_CONSTEXPR20 void range_initialize(Iterator first, Iterator last) {
260 size_type n = _MSTL distance(first, last);
261 start_ = this->allocate_and_copy(n, first, last);
262 finish_ = start_ + n;
263 pair_.value = finish_;
264 }
265
266 MSTL_CONSTEXPR20 void deallocate() {
267 if (start_) pair_.get_base().deallocate(start_, pair_.value - start_);
268 }
269
270 template <typename Iterator>
271 MSTL_CONSTEXPR20 void range_insert(iterator position, Iterator first, Iterator last) {
272 if (first == last) return;
273 const size_t n = _MSTL distance(first, last);
274 if (static_cast<size_t>(pair_.value - finish_) >= n) {
275 const auto elems_after = static_cast<size_t>(this->end() - position);
276 iterator old_finish = this->end();
277 if (elems_after > n) {
278 _MSTL uninitialized_copy(finish_ - n, finish_, finish_);
279 finish_ += n;
280 _MSTL copy_backward(position, old_finish - n, old_finish);
281 _MSTL copy(first, last, position);
282 }
283 else {
284 Iterator mid = first;
285 _MSTL advance(mid, elems_after);
286 _MSTL uninitialized_copy(mid, last, finish_);
287 finish_ += (n - elems_after);
288 _MSTL uninitialized_move(position, old_finish, finish_);
289 finish_ += elems_after;
290 _MSTL copy(first, mid, position);
291 }
292 }
293 else {
294 const size_type old_size = this->size();
295 const size_type len = old_size + _MSTL max(old_size, n);
296 pointer new_start = pair_.get_base().allocate(len);
297 pointer new_finish = new_start;
298 new_finish = _MSTL uninitialized_copy(this->begin(), position, new_start);
299 new_finish = _MSTL uninitialized_copy(first, last, new_finish);
300 new_finish = _MSTL uninitialized_copy(position, this->end(), new_finish);
301 _MSTL destroy(start_, finish_);
302 this->deallocate();
303 start_ = new_start;
304 finish_ = new_finish;
305 pair_.value = new_start + len;
306 }
307 }
308
309 template <typename Iterator, enable_if_t<!is_ranges_fwd_iter_v<Iterator>, int> = 0>
310 MSTL_CONSTEXPR20 void assign_aux(Iterator first, Iterator last) {
311 pointer cur = start_;
312 for (; first != last && cur != finish_; ++first, ++cur)
313 *cur = *first;
314 if (first == last)
315 this->erase(cur, finish_);
316 else
317 this->insert(finish_, first, last);
318 }
319
320 template <typename Iterator, enable_if_t<is_ranges_fwd_iter_v<Iterator>, int> = 0>
321 MSTL_CONSTEXPR20 void assign_aux(Iterator first, Iterator last) {
322 const size_t n = _MSTL distance(first, last);
323 if (n > this->capacity()) {
324 this->clear();
325 this->range_insert(this->begin(), first, last);
326 }
327 else if (n > size()) {
328 Iterator mid = first;
329 _MSTL advance(mid, this->size());
330 _MSTL copy(first, mid, this->begin());
331 finish_ = _MSTL uninitialized_copy(mid, last, finish_);
332 }
333 else {
334 _MSTL copy(first, last, this->begin());
335 this->erase(this->begin() + n, this->end());
336 }
337 }
338
339public:
340 MSTL_CONSTEXPR20 vector() {
341 constexpr size_type init_cap = 1;
342 pointer result = pair_.get_base().allocate(init_cap);
343 finish_ = start_ = result;
344 pair_.value = finish_ + init_cap;
345 }
346
347 MSTL_CONSTEXPR20 explicit vector(const size_type n) {
348 start_ = pair_.get_base().allocate(n);
349 finish_ = start_;
350 try {
351 for (size_type i = 0; i < n; ++i) {
352 _MSTL construct(finish_);
353 ++finish_;
354 }
355 } catch (...) {
356 _MSTL destroy(start_, finish_);
357 pair_.get_base().deallocate(start_, n);
358 throw;
359 }
360 pair_.value = start_ + n;
361 }
362 MSTL_CONSTEXPR20 explicit vector(const size_type n, const T& value) {
363 this->fill_initialize(n, value);
364 }
365 MSTL_CONSTEXPR20 explicit vector(const int16_t n, const T& value) {
366 this->fill_initialize(n, value);
367 }
368 MSTL_CONSTEXPR20 explicit vector(const int32_t n, const T& value) {
369 this->fill_initialize(n, value);
370 }
371 MSTL_CONSTEXPR20 explicit vector(const int64_t n, const T& value) {
372 this->fill_initialize(n, value);
373 }
374
375 MSTL_CONSTEXPR20 vector(const vector& x) {
376 start_ = this->allocate_and_copy(x.cend() - x.cbegin(), x.cbegin(), x.cend());
377 finish_ = start_ + (x.cend() - x.cbegin());
378 pair_.value = finish_;
379 }
380 MSTL_CONSTEXPR20 vector& operator =(const vector& x) {
381 if (_MSTL addressof(x) == this) return *this;
382 this->clear();
383 this->insert(this->end(), x.cbegin(), x.cend());
384 return *this;
385 }
386
387 MSTL_CONSTEXPR20 vector(vector&& x) noexcept {
388 this->swap(x);
389 }
390 MSTL_CONSTEXPR20 vector& operator =(vector&& x) noexcept {
391 if (_MSTL addressof(x) == this) return *this;
392 this->clear();
393 this->swap(x);
394 return *this;
395 }
396
397 template <typename Iterator>
398 MSTL_CONSTEXPR20 vector(Iterator first, Iterator last) {
399 MSTL_DEBUG_VERIFY(first <= last, "vector iterator-constructor out of ranges.");
400 this->range_initialize(first, last);
401 }
402
403 MSTL_CONSTEXPR20 vector(std::initializer_list<T> x)
404 : vector(x.begin(), x.end()) {}
405
406 MSTL_CONSTEXPR20 vector& operator =(std::initializer_list<T> x) {
407 if (x.size() > this->capacity()) {
408 pointer new_ = this->allocate_and_move(x.end() - x.begin(), x.begin(), x.end());
409 _MSTL destroy(start_, finish_);
410 this->deallocate();
411 start_ = new_;
412 finish_ = start_ + x.size();
413 pair_.value = start_ + x.size();
414 }
415 else if (size() >= x.size()) {
416 iterator i = _MSTL copy(x.begin(), x.end(), this->begin());
417 _MSTL destroy(i.base(), finish_);
418 }
419 else {
420 _MSTL copy(x.begin(), x.begin() + this->size(), start_);
421 _MSTL uninitialized_copy(x.begin() + this->size(), x.end(), finish_);
422 }
423 finish_ = start_ + x.size();
424 return *this;
425 }
426
427 MSTL_CONSTEXPR20 ~vector() {
428 this->clear();
429 this->deallocate();
430 }
431
432 MSTL_NODISCARD MSTL_CONSTEXPR20 iterator begin() noexcept { return iterator(start_, this); }
433 MSTL_NODISCARD MSTL_CONSTEXPR20 iterator end() noexcept { return iterator(finish_, this); }
434 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator begin() const noexcept { return this->cbegin(); }
435 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator end() const noexcept { return this->cend(); }
436 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator cbegin() const noexcept { return const_iterator(start_, this); }
437 MSTL_NODISCARD MSTL_CONSTEXPR20 const_iterator cend() const noexcept { return const_iterator(finish_, this); }
438 MSTL_NODISCARD MSTL_CONSTEXPR20 reverse_iterator rbegin() noexcept { return reverse_iterator(this->end()); }
439 MSTL_NODISCARD MSTL_CONSTEXPR20 reverse_iterator rend() noexcept { return reverse_iterator(this->begin()); }
440 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator rbegin() const noexcept { return this->crbegin(); }
441 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator rend() const noexcept { return this->crend(); }
442 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->cend()); }
443 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->cbegin()); }
444
445 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type size() const noexcept {
446 return static_cast<size_type>(finish_ - start_);
447 }
448 MSTL_NODISCARD static constexpr size_type max_size() noexcept {
449 return static_cast<size_type>(-1) / sizeof(T);
450 }
451 MSTL_NODISCARD MSTL_CONSTEXPR20 size_type capacity() const noexcept {
452 return static_cast<size_type>(pair_.value - start_);
453 }
454 MSTL_NODISCARD MSTL_CONSTEXPR20 bool empty() const noexcept {
455 return start_ == finish_;
456 }
457
458 MSTL_NODISCARD MSTL_CONSTEXPR20 pointer data() noexcept {
459 MSTL_DEBUG_VERIFY(!empty(), "data called on empty vector");
460 return start_;
461 }
462 MSTL_NODISCARD MSTL_CONSTEXPR20 const_pointer data() const noexcept {
463 MSTL_DEBUG_VERIFY(!empty(), "data called on empty vector");
464 return start_;
465 }
466
467 MSTL_NODISCARD MSTL_CONSTEXPR20 allocator_type get_allocator() const noexcept { return allocator_type(); }
468
469 MSTL_NODISCARD MSTL_CONSTEXPR20 reference front() noexcept {
470 MSTL_DEBUG_VERIFY(!empty(), "front called on empty vector");
471 return *start_;
472 }
473 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference front() const noexcept {
474 MSTL_DEBUG_VERIFY(!empty(), "front called on empty vector");
475 return *start_;
476 }
477 MSTL_NODISCARD MSTL_CONSTEXPR20 reference back() noexcept {
478 MSTL_DEBUG_VERIFY(!empty(), "back called on empty vector");
479 return *(finish_ - 1);
480 }
481 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference back() const noexcept {
482 MSTL_DEBUG_VERIFY(!empty(), "back called on empty vector");
483 return *(finish_ - 1);
484 }
485
486 MSTL_CONSTEXPR20 void reserve(const size_type n) {
487 MSTL_DEBUG_VERIFY(n < max_size(), "vector reserve out of allocate bounds.");
488 if (this->capacity() >= n) return;
489
490 size_type new_capacity = _MSTL max(this->capacity() * 2, n);
491 pointer new_start = pair_.get_base().allocate(new_capacity);
492 pointer new_finish = new_start;
493
494 try {
495 new_finish = _MSTL uninitialized_move(start_, finish_, new_start);
496 } catch (...) {
497 _MSTL destroy(new_start, new_finish);
498 pair_.get_base().deallocate(new_start, new_capacity);
499 throw;
500 }
501
502 _MSTL destroy(start_, finish_);
503 this->deallocate();
504 start_ = new_start;
505 finish_ = new_finish;
506 pair_.value = start_ + new_capacity;
507 }
508
509 MSTL_CONSTEXPR20 void resize(size_type new_size, const T& x) {
510 if (new_size < this->size()) {
511 this->erase(this->begin() + new_size, this->end());
512 } else {
513 this->insert(this->end(), new_size - this->size(), x);
514 }
515 }
516 MSTL_CONSTEXPR20 void resize(const size_type new_size) {
517 this->resize(new_size, T());
518 }
519
520 template <typename... Args>
521 MSTL_CONSTEXPR20 void emplace(iterator position, Args&&... args) {
522 if (finish_ != pair_.value) {
523 _MSTL construct(finish_, _MSTL move(*(finish_ - 1)));
524 ++finish_;
525 _MSTL move_backward(position, _MSTL prev(this->end(), -2), _MSTL prev(this->end()));
526 _MSTL construct(&*position, _MSTL forward<Args>(args)...);
527 return;
528 }
529 const size_type old_size = this->size();
530 const size_type len = old_size != 0 ? 2 * old_size : 1;
531 pointer new_start = pair_.get_base().allocate(len);
532 pointer new_finish = _MSTL uninitialized_move(begin(), position, new_start);
533 _MSTL construct(new_finish, _MSTL forward<Args>(args)...);
534 ++new_finish;
535 new_finish = _MSTL uninitialized_move(position, end(), new_finish);
536 _MSTL destroy(begin(), end());
537 deallocate();
538 start_ = new_start;
539 finish_ = new_finish;
540 pair_.value = new_start + len;
541 }
542
543 template <typename... Args>
544 MSTL_CONSTEXPR20 void emplace_back(Args&&... args) {
545 if (finish_ != pair_.value) {
546 _MSTL construct(finish_, _MSTL forward<Args>(args)...);
547 ++finish_;
548 }
549 else this->emplace(this->end(), _MSTL forward<Args>(args)...);
550 }
551
552 MSTL_CONSTEXPR20 void push_back(const T& val) {
553 if (finish_ != pair_.value) {
554 _MSTL construct(finish_, val);
555 ++finish_;
556 }
557 else this->emplace(this->end(), val);
558 }
559 MSTL_CONSTEXPR20 void push_back(T&& val) {
560 this->emplace_back(_MSTL move(val));
561 }
562
563 MSTL_CONSTEXPR20 void pop_back() noexcept {
564 MSTL_DEBUG_VERIFY(!empty(), "pop called in an empty vector")
565 _MSTL destroy(finish_ - 1);
566 --finish_;
567 }
568
569 MSTL_CONSTEXPR20 void assign(size_type n, const value_type& value) {
570 if (n > this->capacity()) {
571 this->clear();
572 this->reserve(n);
573 this->insert(this->begin(), n, value);
574 }
575 else if (n > this->size()) {
576 _MSTL fill(this->begin(), this->end(), value);
577 finish_ = _MSTL uninitialized_fill_n(finish_, n - this->size(), value);
578 }
579 else {
580 _MSTL fill_n(this->begin(), n, value);
581 this->erase(this->begin() + n, this->end());
582 }
583 }
584
585 template <typename Iterator, enable_if_t<is_iter_v<Iterator>, int> = 0>
586 MSTL_CONSTEXPR20 void assign(Iterator first, Iterator last) {
587 this->assign_aux(first, last);
588 }
589
590 MSTL_CONSTEXPR20 void assign(std::initializer_list<value_type> l) {
591 this->assign(l.begin(), l.end());
592 }
593
594 MSTL_CONSTEXPR20 iterator insert(iterator position, const value_type& x) {
595 size_type n = position - this->begin();
596 this->emplace(position, x);
597 return this->begin() + n;
598 }
599 MSTL_CONSTEXPR20 iterator insert(iterator position, value_type&& x) {
600 size_type n = position - this->begin();
601 this->emplace(position, _MSTL move(x));
602 return this->begin() + n;
603 }
604
605 MSTL_CONSTEXPR20 iterator insert(iterator position) {
606 return this->insert(position, T());
607 }
608
609 template <typename Iterator>
610 MSTL_CONSTEXPR20 void insert(iterator position, Iterator first, Iterator last) {
611 MSTL_DEBUG_VERIFY(
612 _MSTL distance(first, last) >= 0, "vector insert resource iterator out of ranges."
613 );
614 this->range_insert(position, first, last);
615 }
616
617 MSTL_CONSTEXPR20 void insert(iterator position, std::initializer_list<value_type> l) {
618 this->range_insert(position, l.begin(), l.end());
619 }
620 MSTL_CONSTEXPR20 void insert(iterator position, size_type n, const value_type& x) {
621 if (n == 0) return;
622 if (static_cast<size_type>(pair_.value - finish_) >= n) {
623 const size_type elems_after = _MSTL distance(this->begin(), position);
624 iterator old_finish = this->end();
625 if (elems_after > n) {
626 _MSTL uninitialized_copy(finish_ - n, finish_, finish_);
627 finish_ += n;
628 _MSTL copy_backward(position, old_finish - n, old_finish);
629 _MSTL fill(position, position + n, x);
630 }
631 else {
632 _MSTL uninitialized_fill_n(finish_, n - elems_after, x);
633 finish_ += n - elems_after;
634 _MSTL uninitialized_move(position, old_finish, this->end());
635 finish_ += elems_after;
636 _MSTL destroy(position, old_finish);
637 _MSTL uninitialized_fill(position, old_finish, x);
638 }
639 }
640 else {
641 const size_type old_size = this->size();
642 const size_type len = old_size + _MSTL max(old_size, n);
643 pointer new_start = pair_.get_base().allocate(len);
644 pointer new_finish = _MSTL uninitialized_copy(this->begin(), position, new_start);
645 new_finish = _MSTL uninitialized_fill_n(new_finish, n, x);
646 new_finish = _MSTL uninitialized_copy(position, this->end(), new_finish);
647 _MSTL destroy(start_, finish_);
648 this->deallocate();
649 start_ = new_start;
650 finish_ = new_finish;
651 pair_.value = new_start + len;
652 }
653 }
654
655 MSTL_CONSTEXPR20 iterator erase(iterator first, iterator last)
656 noexcept(is_nothrow_move_assignable_v<value_type>) {
657 MSTL_DEBUG_VERIFY(_MSTL distance(first, last) >= 0, "vector erase out of ranges.");
658
659 const auto elems_after = this->end() - last;
660 if (elems_after > 0) {
661 _MSTL move_backward(last, this->end(), first + elems_after);
662 }
663 pointer new_finish = finish_ - (last - first);
664 _MSTL destroy(new_finish, finish_);
665 finish_ = new_finish;
666 return first;
667 }
668
669 MSTL_CONSTEXPR20 iterator erase(iterator position)
670 noexcept(is_nothrow_move_assignable_v<value_type>) {
671 if (position + 1 != this->end()) {
672 _MSTL move(position + 1, this->end(), position);
673 }
674 --finish_;
675 _MSTL destroy(finish_);
676 return position;
677 }
678
679 MSTL_CONSTEXPR20 void shrink_to_fit() {
680 if (this->capacity() == this->size()) return;
681 if (this->size() == 0) {
682 this->deallocate();
683 start_ = finish_ = pair_.value = nullptr;
684 return;
685 }
686 pointer new_start = pair_.get_base().allocate(this->size());
687 pointer new_finish = new_start;
688 try {
689 new_finish = _MSTL uninitialized_move(start_, finish_, new_start);
690 } catch (...) {
691 _MSTL destroy(new_start, new_finish);
692 pair_.get_base().deallocate(new_start, this->size());
693 throw;
694 }
695 _MSTL destroy(start_, finish_);
696 this->deallocate();
697 start_ = new_start;
698 finish_ = new_finish;
699 pair_.value = new_start + this->size();
700 }
701
702 MSTL_CONSTEXPR20 void clear() noexcept {
703 if (this->empty()) return;
704 _MSTL destroy(start_, finish_);
705 finish_ = start_;
706 }
707
708 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference at(const size_type position) const noexcept {
709 MSTL_DEBUG_VERIFY(position < this->size(), "vector access out of range");
710 return *(start_ + position);
711 }
712 MSTL_NODISCARD MSTL_CONSTEXPR20 reference at(const size_type position) noexcept {
713 return const_cast<reference>(static_cast<const vector*>(this)->at(position));
714 }
715 MSTL_NODISCARD MSTL_CONSTEXPR20 const_reference operator [](const size_type position) const noexcept {
716 return this->at(position);
717 }
718 MSTL_NODISCARD MSTL_CONSTEXPR20 reference operator [](const size_type position) noexcept {
719 return this->at(position);
720 }
721
722 MSTL_CONSTEXPR20 void swap(vector& x) noexcept {
723 if (_MSTL addressof(x) == this) return;
724 _MSTL swap(start_, x.start_);
725 _MSTL swap(finish_, x.finish_);
726 _MSTL swap(pair_, x.pair_);
727 }
728
729 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator ==(const vector& rhs) const
730 noexcept(noexcept(this->size() == rhs.size() && _MSTL equal(this->cbegin(), this->cend(), rhs.cbegin()))) {
731 return this->size() == rhs.size() && _MSTL equal(this->cbegin(), this->cend(), rhs.cbegin());
732 }
733 MSTL_NODISCARD MSTL_CONSTEXPR20 bool operator <(const vector& rhs) const
734 noexcept(noexcept(_MSTL lexicographical_compare(this->cbegin(), this->cend(), rhs.cbegin(), rhs.cend()))) {
735 return _MSTL lexicographical_compare(this->cbegin(), this->cend(), rhs.cbegin(), rhs.cend());
736 }
737};
738#if MSTL_SUPPORT_DEDUCTION_GUIDES__
739template <typename T, typename Alloc>
740vector(T, Alloc = Alloc()) -> vector<T, Alloc>;
741
742template <typename Iterator, typename Alloc>
743vector(Iterator, Iterator, Alloc = Alloc()) -> vector<iter_value_t<Iterator>, Alloc>;
744#endif
745
746using bvector = vector<byte_t>;
747
748
750#endif // MSTL_CORE_CONTAINER_VECTOR_HPP__
MSTL比较算法
MSTL压缩对实现
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr const T & max(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(a, b)))
返回两个值中的较大者
MSTL_NODISCARD constexpr bool equal(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryPredicate binary_pred) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(binary_pred(*first1, *first2)))
比较两个范围是否相等
MSTL_NODISCARD constexpr bool lexicographical_compare(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Compare comp) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(comp(*first1, *first2)) &&noexcept(first1==last1 &&first2 !=last2))
字典序比较两个范围
long long int64_t
64位有符号整数类型
short int16_t
16位有符号整数类型
int int32_t
32位有符号整数类型
MSTL_CONSTEXPR20 enable_if_t< is_constructible_v< T, Args... >, void * > construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
MSTL_CONSTEXPR20 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
MSTL_INLINE17 constexpr bool is_iter_v
检查类型是否为迭代器
MSTL_INLINE17 constexpr bool is_ranges_fwd_iter_v
检查是否为范围前向迭代器
constexpr Iterator prev(Iterator iter, iter_difference_t< Iterator > n=-1)
获取迭代器的前一个位置
constexpr iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
constexpr void advance(Iterator &i, Distance n)
将迭代器前进指定距离
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BUILD_TYPE_ALIAS(TYPE)
快速构建标准类型别名
constexpr Iterator2 copy_backward(Iterator1 first, Iterator1 last, Iterator2 result)
反向复制范围元素
constexpr void fill(Iterator first, Iterator last, const T &value)
填充范围元素
constexpr Iterator2 move_backward(Iterator1 first, Iterator1 last, Iterator2 result)
反向移动范围元素
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
constexpr Iterator2 copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制范围元素
constexpr Iterator fill_n(Iterator first, size_t n, const T &value)
填充指定数量的元素
void swap()=delete
删除无参数的swap重载
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL_CONSTEXPR20 Iterator2 uninitialized_move(Iterator1 first, Iterator1 last, Iterator2 result)
在未初始化内存中移动元素
MSTL_CONSTEXPR20 Iterator uninitialized_fill_n(Iterator first, size_t n, const T &x)
在未初始化内存中用指定值填充指定数量的元素
MSTL_CONSTEXPR20 void uninitialized_fill(Iterator first, Iterator last, const T &x)
在未初始化内存上填充值
MSTL_CONSTEXPR20 Iterator2 uninitialized_copy(Iterator1 first, Iterator1 last, Iterator2 result)
复制元素到未初始化内存
MSTL集合器接口
MSTL标准分配器
集合器接口模板
MSTL_NODISCARD constexpr decltype(auto) size() const noexcept(noexcept(derived().size()))
获取集合大小
MSTL_NODISCARD constexpr bool empty() const noexcept(noexcept(derived().empty()))
检查集合是否为空
MSTL未初始化内存操作