MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
list.hpp
1#ifndef MSTL_CORE_CONTAINER_LIST_HPP__
2#define MSTL_CORE_CONTAINER_LIST_HPP__
5
6template <typename T, typename Alloc>
7class list;
8template <bool IsConst, typename List>
9struct list_iterator;
10
11template <typename T>
12struct list_node {
13private:
14 using value_type = T;
15 using node_type = list_node<value_type>;
16
17 value_type data_{};
18 node_type* prev_ = nullptr;
19 node_type* next_ = nullptr;
20
21 template <typename, typename> friend class list;
22 template <bool, typename> friend struct list_iterator;
23};
24
25template <bool IsConst, typename List>
26struct list_iterator {
27private:
28 using container_type = List;
29 using iterator = list_iterator<false, container_type>;
30 using const_iterator = list_iterator<true, container_type>;
31
32public:
33 using iterator_category = bidirectional_iterator_tag;
34 using value_type = typename container_type::value_type;
37 using difference_type = typename container_type::difference_type;
38 using size_type = typename container_type::size_type;
39
40private:
41 using node_type = list_node<value_type>;
42
43 node_type* node_ = nullptr;
44 const container_type* list_ = nullptr;
45
46 template <typename, typename> friend class list;
47 template <bool, typename> friend struct list_iterator;
48
49public:
50 list_iterator() noexcept = default;
51 list_iterator(node_type* x, const container_type* list) noexcept
52 : node_(x), list_(list) {}
53
54 list_iterator(const iterator& x) noexcept
55 : node_(x.node_), list_(x.list_) {}
56
57 list_iterator& operator =(const iterator& x) noexcept {
58 if(_MSTL addressof(x) == this) return *this;
59 node_ = x.node_;
60 list_ = x.list_;
61 return *this;
62 }
63
64 list_iterator(const const_iterator& x) noexcept
65 : node_(x.node_), list_(x.list_) {}
66
67 list_iterator& operator =(const const_iterator& x) noexcept {
68 if(_MSTL addressof(x) == this) return *this;
69 node_ = x.node_;
70 list_ = x.list_;
71 return *this;
72 }
73
74 list_iterator(iterator&& x) noexcept : node_(x.node_), list_(x.list_) {
75 x.node_ = nullptr;
76 x.list_ = nullptr;
77 }
78
79 list_iterator& operator =(iterator&& x) noexcept {
80 if(_MSTL addressof(x) == this) return *this;
81 node_ = x.node_;
82 list_ = x.list_;
83 x.node_ = nullptr;
84 x.list_ = nullptr;
85 return *this;
86 }
87
88 list_iterator(const_iterator&& x) noexcept
89 : node_(x.node_), list_(x.list_) {
90 x.node_ = nullptr;
91 x.list_ = nullptr;
92 }
93
94 list_iterator& operator =(const_iterator&& x) noexcept {
95 if(_MSTL addressof(x) == this) return *this;
96 node_ = x.node_;
97 list_ = x.list_;
98 x.node_ = nullptr;
99 x.list_ = nullptr;
100 return *this;
101 }
102
103 ~list_iterator() = default;
104
105 MSTL_NODISCARD reference operator *() const noexcept {
106 MSTL_DEBUG_VERIFY(list_ && node_ && node_ != list_->head_,
107 __MSTL_DEBUG_MESG_OPERATE_NULLPTR(list_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
108 return node_->data_;
109 }
110 MSTL_NODISCARD pointer operator->() const noexcept {
111 return &operator*();
112 }
113
114 list_iterator& operator ++() noexcept {
115 MSTL_DEBUG_VERIFY(list_ && node_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(list_iterator, __MSTL_DEBUG_TAG_INCREMENT));
116 MSTL_DEBUG_VERIFY(node_ != list_->head_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(list_iterator, __MSTL_DEBUG_TAG_INCREMENT));
117 node_ = node_->next_;
118 return *this;
119 }
120 list_iterator operator ++(int) noexcept {
121 list_iterator old = *this;
122 ++*this;
123 return old;
124 }
125 list_iterator& operator --() noexcept {
126 MSTL_DEBUG_VERIFY(list_ && node_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(list_iterator, __MSTL_DEBUG_TAG_DECREMENT));
127 MSTL_DEBUG_VERIFY(node_->prev_ != list_->head_, __MSTL_DEBUG_MESG_OUT_OF_RANGE(list_iterator, __MSTL_DEBUG_TAG_DECREMENT));
128 node_ = node_->prev_;
129 return *this;
130 }
131 list_iterator operator --(int) noexcept {
132 list_iterator old = *this;
133 --*this;
134 return old;
135 }
136
137 MSTL_NODISCARD bool operator ==(const list_iterator& x) noexcept {
138 MSTL_DEBUG_VERIFY(list_ == x.list_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(list_iterator));
139 return node_ == x.node_;
140 }
141 MSTL_NODISCARD bool operator !=(const list_iterator& x) noexcept {
142 return !(*this == x);
143 }
144
145 MSTL_NODISCARD pointer base() const noexcept {
146 return node_;
147 }
148};
149
150
151template <typename T, typename Alloc = allocator<list_node<T>>>
152class list : public icollector<list<T, Alloc>> {
153#ifdef MSTL_STANDARD_20__
154 static_assert(is_allocator_v<Alloc>, "Alloc type is not a standard allocator type.");
155#endif
156 static_assert(is_same_v<list_node<T>, typename Alloc::value_type>, "allocator type mismatch.");
157 static_assert(is_object_v<T>, "list only contains object types.");
158
159public:
161 using allocator_type = Alloc;
162 using iterator = list_iterator<false, list>;
163 using const_iterator = list_iterator<true, list>;
164 using reverse_iterator = _MSTL reverse_iterator<iterator>;
165 using const_reverse_iterator = _MSTL reverse_iterator<const_iterator>;
166
167private:
168 using node_type = list_node<T>;
169 using link_type = node_type*;
170
171 link_type head_ = nullptr;
172 compressed_pair<allocator_type, size_type> pair_{ default_construct_tag{}, 0 };
173
174 template <bool, typename> friend struct list_iterator;
175
176private:
177 template <typename... Args>
178 link_type create_node(Args&&... args) {
179 link_type p = pair_.get_base().allocate();
180 _MSTL construct(&p->data_, _MSTL forward<Args>(args)...);
181 return p;
182 }
183 void destroy_node(link_type p) noexcept {
184 _MSTL destroy(p);
185 pair_.get_base().deallocate(p);
186 }
187
188 void empty_init() {
189 head_ = create_node();
190 head_->prev_ = head_->next_ = head_;
191 }
192
193public:
194 list() {
195 empty_init();
196 }
197 explicit list(size_type n) {
198 empty_init();
199 while (n--) push_back(value_type());
200 };
201
202 list(size_type n, const T& x) {
203 empty_init();
204 while (n--) push_back(x);
205 };
206
207 template <typename Iterator, enable_if_t<is_ranges_input_iter_v<Iterator>, int> = 0>
208 list(Iterator first, Iterator last) {
209 empty_init();
210 while (first != last) {
211 push_back(*first);
212 ++first;
213 }
214 };
215
216 list(std::initializer_list<T> l) : list(l.begin(), l.end()) {}
217
218 list& operator =(std::initializer_list<T> l) {
219 clear();
220 insert(begin(), l.begin(), l.end());
221 return *this;
222 }
223
224 list(const list& x) : list(x.cbegin(), x.cend()) {}
225
226 list& operator =(const list& x) {
227 if (_MSTL addressof(x) == this) return *this;
228 clear();
229 link_type p = x.head_->next_;
230 while (p != x.head_) {
231 link_type q = this->create_node(p->data_);
232 q->prev_ = head_->prev_;
233 q->next_ = head_;
234 head_->prev_->next_ = q;
235 head_->prev_ = q;
236 p = p->next_;
237 }
238 pair_.value = x.pair_.value;
239 return *this;
240 }
241
242 list(list&& x) noexcept {
243 empty_init();
244 this->swap(x);
245 }
246 list& operator =(list&& x) noexcept {
247 if (_MSTL addressof(x) == this) return *this;
248 this->swap(x);
249 return *this;
250 }
251
252 ~list() {
253 link_type p = head_->next_;
254 while (p != head_) {
255 link_type q = p;
256 p = p->next_;
257 this->destroy_node(q);
258 }
259 this->destroy_node(head_);
260 }
261
262 MSTL_NODISCARD iterator begin() noexcept { return {head_->next_, this}; }
263 MSTL_NODISCARD iterator end() noexcept { return {head_, this}; }
264 MSTL_NODISCARD const_iterator begin() const noexcept { return cbegin(); }
265 MSTL_NODISCARD const_iterator end() const noexcept { return cend(); }
266 MSTL_NODISCARD const_iterator cbegin() const noexcept { return {head_->next_, this}; }
267 MSTL_NODISCARD const_iterator cend() const noexcept { return {head_, this}; }
268 MSTL_NODISCARD reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
269 MSTL_NODISCARD reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
270 MSTL_NODISCARD const_reverse_iterator rbegin() const noexcept { return crbegin(); }
271 MSTL_NODISCARD const_reverse_iterator rend() const noexcept { return crend(); }
272 MSTL_NODISCARD const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
273 MSTL_NODISCARD const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
274
275 MSTL_NODISCARD size_type size() const noexcept { return pair_.value; }
276 MSTL_NODISCARD size_type max_size() const noexcept { return static_cast<size_type>(-1); }
277 MSTL_NODISCARD bool empty() const noexcept { return head_->next_ == head_; }
278
279 MSTL_NODISCARD allocator_type get_allocator() { return allocator_type(); }
280
281 MSTL_NODISCARD reference front() noexcept {
282 MSTL_DEBUG_VERIFY(!empty(), "front called on empty list");
283 return head_->next_->data_;
284 }
285 MSTL_NODISCARD const_reference front() const noexcept {
286 MSTL_DEBUG_VERIFY(!empty(), "front called on empty list");
287 return head_->next_->data_;
288 }
289 MSTL_NODISCARD reference back() noexcept {
290 MSTL_DEBUG_VERIFY(!empty(), "back called on empty list");
291 return head_->prev_->data_;
292 }
293 MSTL_NODISCARD const_reference back() const noexcept {
294 MSTL_DEBUG_VERIFY(!empty(), "back called on empty list");
295 return head_->prev_->data_;
296 }
297
298 template <typename... U>
299 iterator emplace(iterator position, U&&... args) {
300 link_type temp = (create_node)(_MSTL forward<U>(args)...);
301 temp->next_ = position.node_;
302 temp->prev_ = position.node_->prev_;
303 position.node_->prev_->next_ = temp;
304 position.node_->prev_ = temp;
305 ++pair_.value;
306 return {temp, this};
307 }
308
309 template <typename... Args>
310 iterator emplace_back(Args&&... args) {
311 return (emplace)(end(), _MSTL forward<Args>(args)...);
312 }
313 template <typename... Args>
314 iterator emplace_front(Args&&... args) {
315 return (emplace)(begin(), _MSTL forward<Args>(args)...);
316 }
317
318 void push_front(const T& x) { insert(begin(), x); }
319 void push_front(T&& x) { insert(begin(), _MSTL forward<T>(x)); }
320 void push_back(const T& x) { insert(end(), x); }
321 void push_back(T&& x) { insert(end(), _MSTL forward<T>(x)); }
322
323 void pop_front() noexcept { erase(begin()); }
324 void pop_back() noexcept { erase({head_->prev_, this}); }
325
326 void assign(size_type count, const T& value) {
327 clear();
328 insert(begin(), count, value);
329 }
330
331 template <typename Iterator, enable_if_t<is_ranges_input_iter_v<Iterator>, int> = 0>
332 void assign(Iterator first, Iterator last) {
333 clear();
334 insert(begin(), first, last);
335 }
336
337 void assign(std::initializer_list<T> l) {
338 assign(l.begin(), l.end());
339 }
340
341 iterator insert(iterator position, const T& x) {
342 return (emplace)(position, x);
343 }
344 iterator insert(iterator position, T&& x) {
345 return (emplace)(position, _MSTL forward<T>(x));
346 }
347
348 template <typename InputIterator>
349 void insert(iterator position, InputIterator first, InputIterator last) {
350 for (--last; first != last; --last)
351 position = insert(position, *last);
352 insert(position, *last);
353 }
354 void insert(iterator position, std::initializer_list<T> l) {
355 insert(position, l.begin(), l.end());
356 }
357
358 void insert(iterator position, size_type n, const T& x) {
359 link_type prev = position.node_->prev_;
360 while (n--) {
361 link_type temp = this->create_node(x);
362 temp->prev_ = prev;
363 temp->next_ = prev->next_;
364 prev->next_->prev_ = temp;
365 prev->next_ = temp;
366 prev = temp;
367 ++pair_.value;
368 }
369 }
370
371 iterator erase(iterator position) noexcept {
372 if (empty()) return end();
373 link_type ret = position.node_->next_;
374 position.node_->prev_->next_ = position.node_->next_;
375 position.node_->next_->prev_ = position.node_->prev_;
376 destroy_node(position.node_);
377 --pair_.value;
378 return {ret, this};
379 }
380 iterator erase(iterator first, iterator last) noexcept {
381 while (first != last) first = erase(first);
382 return first;
383 }
384 void clear() noexcept {
385 link_type cur = head_->next_;
386 while (cur != head_) {
387 link_type temp = cur;
388 cur = cur->next_;
389 destroy_node(temp);
390 --pair_.value;
391 }
392 head_->prev_ = head_;
393 head_->next_ = head_;
394 }
395
396 void swap(list& x) noexcept {
397 _MSTL swap(head_, x.head_);
398 _MSTL swap(pair_, x.pair_);
399 }
400
401 void transfer(iterator position, iterator first, iterator last) {
402 if (position == last) return;
403 last.node_->prev_->next_ = position.node_;
404 first.node_->prev_->next_ = last.node_;
405 position.node_->prev_->next_ = first.node_;
406 link_type tmp = position.node_->prev_;
407 position.node_->prev_ = last.node_->prev_;
408 last.node_->prev_ = first.node_->prev_;
409 first.node_->prev_ = tmp;
410 }
411
412 template <typename Pred>
413 void remove_if(Pred pred) {
414 iterator iter = begin(), last = end();
415 while (iter != last) {
416 if (pred(*iter)) iter = erase(iter);
417 else ++iter;
418 }
419 }
420 void remove(const T& x) {
421 return this->remove_if([&](const T& oth) -> bool { return oth == x; });
422 }
423
424 void splice(iterator position, list& x) {
425 if (!x.empty())
426 transfer(position, x.begin(), x.end());
427 }
428 void splice(iterator position, list&, iterator i) {
429 iterator j = i;
430 ++j;
431 if (i == position || j == position) return;
432 transfer(position, i, j);
433 }
434 void splice(iterator position, list&, iterator first, iterator last) {
435 if (first != last) transfer(position, first, last);
436 }
437
438 template <typename Pred>
439 void merge(list& x, Pred pred) {
440 iterator first1 = begin(), first2 = x.begin();
441 iterator last1 = end(), last2 = x.end();
442 while (first1 != last1 && first2 != last2) {
443 if (!pred(*first2, *first1)) {
444 ++first1;
445 }
446 else {
447 iterator temp = first2;
448 ++temp;
449 transfer(first1, first2, temp);
450 first2 = temp;
451 }
452 }
453 if (first2 != last2) {
454 transfer(last1, first2, last2);
455 }
456 }
457 void merge(list& x) {
458 this->merge(x, _MSTL less<T>());
459 }
460 template <typename Pred>
461 void merge(list&& x, Pred pred) {
462 iterator first1 = begin(), first2 = x.begin();
463 iterator last1 = end(), last2 = x.end();
464 while (first1 != last1 && first2 != last2) {
465 if (!pred(*first2, *first1)) {
466 ++first1;
467 }
468 else {
469 iterator temp = first2;
470 ++temp;
471 transfer(first1, first2, temp);
472 first2 = temp;
473 }
474 }
475 if (first2 != last2) {
476 transfer(last1, first2, last2);
477 }
478 x.clear();
479 }
480 void merge(list&& x) {
481 this->merge(_MSTL forward<list>(x), _MSTL less<T>());
482 }
483
484 void reverse() noexcept {
485 if (empty()) return;
486 link_type current = head_;
487 do {
488 _MSTL swap(current->prev_, current->next_);
489 current = current->prev_;
490 } while (current != head_);
491 }
492
493 template <typename Pred>
494 void unique(Pred pred) noexcept {
495 if (empty()) return;
496 iterator current = begin();
497 iterator next = current;
498 while (++next != end()) {
499 if (pred(*current, *next)) {
500 this->erase(next);
501 next = current;
502 } else {
503 current = next;
504 }
505 }
506 }
507 void unique() noexcept {
508 unique(_MSTL equal_to<T>());
509 }
510
511 template <typename Pred>
512 void sort(Pred pred) {
513 if (empty()) return;
514 link_type p = head_->next_->next_;
515 while (p != head_) {
516 T temp = p->data_;
517 link_type prev = p->prev_;
518 while (prev != head_ && pred(temp, prev->data_)) {
519 prev->next_->data_ = prev->data_;
520 prev = prev->prev_;
521 }
522 prev->next_->data_ = temp;
523 p = p->next_;
524 }
525 }
526 void sort() {
527 sort(_MSTL less<T>());
528 }
529
530 MSTL_NODISCARD const_reference at(size_type position) const {
531 const_iterator iter = cbegin();
532 while (position--) ++iter;
533 return iter.node_->data_;
534 }
535 MSTL_NODISCARD reference at(const size_type position) {
536 return const_cast<reference>(
537 static_cast<const list*>(this)->at(position)
538 );
539 }
540 MSTL_NODISCARD const_reference operator [](const size_type position) const {
541 return this->at(position);
542 }
543 MSTL_NODISCARD reference operator [](const size_type position) {
544 return this->at(position);
545 }
546
547 MSTL_NODISCARD bool operator ==(const list& rhs) const
548 noexcept(noexcept(this->size() == rhs.size() && _MSTL equal(this->cbegin(), this->cend(), rhs.cbegin()))) {
549 return this->size() == rhs.size() && _MSTL equal(this->cbegin(), this->cend(), rhs.cbegin());
550 }
551
552 MSTL_NODISCARD bool operator <(const list& rhs) const
553 noexcept(noexcept(_MSTL lexicographical_compare(this->cbegin(), this->cend(), rhs.cbegin(), rhs.cend()))) {
554 return _MSTL lexicographical_compare(this->cbegin(), this->cend(), rhs.cbegin(), rhs.cend());
555 }
556};
557#if MSTL_SUPPORT_DEDUCTION_GUIDES__
558template <typename Iterator, typename Alloc>
559list(Iterator, Iterator, Alloc = Alloc()) -> list<iter_value_t<Iterator>, Alloc>;
560#endif
561
563#endif // MSTL_CORE_CONTAINER_LIST_HPP__
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
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))
字典序比较两个范围
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
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 >)
销毁单个对象
constexpr Iterator prev(Iterator iter, iter_difference_t< Iterator > n=-1)
获取迭代器的前一个位置
constexpr Iterator next(Iterator iter, iter_difference_t< Iterator > n=1)
获取迭代器的后一个位置
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BUILD_TYPE_ALIAS(TYPE)
快速构建标准类型别名
void swap()=delete
删除无参数的swap重载
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
MSTL集合器接口
集合器接口模板