1#ifndef MSTL_CORE_CONTAINER_LIST_HPP__
2#define MSTL_CORE_CONTAINER_LIST_HPP__
6template <
typename T,
typename Alloc>
8template <
bool IsConst,
typename List>
15 using node_type = list_node<value_type>;
18 node_type* prev_ =
nullptr;
19 node_type* next_ =
nullptr;
21 template <
typename,
typename>
friend class list;
22 template <
bool,
typename>
friend struct list_iterator;
25template <
bool IsConst,
typename List>
28 using container_type = List;
29 using iterator = list_iterator<false, container_type>;
30 using const_iterator = list_iterator<true, container_type>;
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;
41 using node_type = list_node<value_type>;
43 node_type* node_ =
nullptr;
44 const container_type* list_ =
nullptr;
46 template <
typename,
typename>
friend class list;
47 template <
bool,
typename>
friend struct list_iterator;
50 list_iterator() noexcept = default;
51 list_iterator(node_type* x, const container_type* list) noexcept
52 : node_(x), list_(list) {}
54 list_iterator(
const iterator& x) noexcept
55 : node_(x.node_), list_(x.list_) {}
57 list_iterator& operator =(
const iterator& x)
noexcept {
64 list_iterator(
const const_iterator& x) noexcept
65 : node_(x.node_), list_(x.list_) {}
67 list_iterator& operator =(
const const_iterator& x)
noexcept {
74 list_iterator(iterator&& x) noexcept : node_(x.node_), list_(x.list_) {
79 list_iterator& operator =(iterator&& x)
noexcept {
88 list_iterator(const_iterator&& x) noexcept
89 : node_(x.node_), list_(x.list_) {
94 list_iterator& operator =(const_iterator&& x)
noexcept {
103 ~list_iterator() =
default;
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));
110 MSTL_NODISCARD pointer operator->() const noexcept {
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_;
120 list_iterator operator ++(
int)
noexcept {
121 list_iterator old = *
this;
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_;
131 list_iterator operator --(
int)
noexcept {
132 list_iterator old = *
this;
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_;
141 MSTL_NODISCARD
bool operator !=(
const list_iterator& x)
noexcept {
142 return !(*
this == x);
145 MSTL_NODISCARD pointer base() const noexcept {
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.");
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.");
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>;
168 using node_type = list_node<T>;
169 using link_type = node_type*;
171 link_type head_ =
nullptr;
172 compressed_pair<allocator_type, size_type> pair_{ default_construct_tag{}, 0 };
174 template <
bool,
typename>
friend struct list_iterator;
177 template <
typename... Args>
178 link_type create_node(Args&&... args) {
179 link_type p = pair_.get_base().allocate();
183 void destroy_node(link_type p)
noexcept {
185 pair_.get_base().deallocate(p);
189 head_ = create_node();
190 head_->prev_ = head_->next_ = head_;
197 explicit list(size_type n) {
199 while (n--) push_back(value_type());
202 list(size_type n,
const T& x) {
204 while (n--) push_back(x);
207 template <
typename Iterator, enable_if_t<is_ranges_input_iter_v<Iterator>,
int> = 0>
208 list(Iterator first, Iterator last) {
210 while (first != last) {
216 list(std::initializer_list<T> l) : list(l.begin(), l.end()) {}
218 list& operator =(std::initializer_list<T> l) {
220 insert(begin(), l.begin(), l.end());
224 list(
const list& x) : list(x.cbegin(), x.cend()) {}
226 list& operator =(
const list& x) {
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_;
234 head_->prev_->next_ = q;
238 pair_.value = x.pair_.
value;
242 list(list&& x)
noexcept {
246 list& operator =(list&& x)
noexcept {
253 link_type p = head_->next_;
257 this->destroy_node(q);
259 this->destroy_node(head_);
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()); }
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_; }
279 MSTL_NODISCARD allocator_type get_allocator() {
return allocator_type(); }
281 MSTL_NODISCARD reference front() noexcept {
282 MSTL_DEBUG_VERIFY(!empty(),
"front called on empty list");
283 return head_->next_->data_;
285 MSTL_NODISCARD const_reference front() const noexcept {
286 MSTL_DEBUG_VERIFY(!empty(),
"front called on empty list");
287 return head_->next_->data_;
289 MSTL_NODISCARD reference back() noexcept {
290 MSTL_DEBUG_VERIFY(!empty(),
"back called on empty list");
291 return head_->prev_->data_;
293 MSTL_NODISCARD const_reference back() const noexcept {
294 MSTL_DEBUG_VERIFY(!empty(),
"back called on empty list");
295 return head_->prev_->data_;
298 template <
typename... U>
299 iterator emplace(iterator position, U&&... args) {
301 temp->next_ = position.node_;
302 temp->prev_ = position.node_->prev_;
303 position.node_->prev_->next_ = temp;
304 position.node_->prev_ = temp;
309 template <
typename... Args>
310 iterator emplace_back(Args&&... args) {
313 template <
typename... Args>
314 iterator emplace_front(Args&&... args) {
318 void push_front(
const T& x) { insert(begin(), x); }
320 void push_back(
const T& x) { insert(end(), x); }
323 void pop_front() noexcept { erase(begin()); }
324 void pop_back() noexcept { erase({head_->prev_,
this}); }
326 void assign(size_type
count,
const T& value) {
328 insert(begin(),
count, value);
331 template <
typename Iterator, enable_if_t<is_ranges_input_iter_v<Iterator>,
int> = 0>
332 void assign(Iterator first, Iterator last) {
334 insert(begin(), first, last);
337 void assign(std::initializer_list<T> l) {
338 assign(l.begin(), l.end());
341 iterator insert(iterator position,
const T& x) {
342 return (emplace)(position, x);
344 iterator insert(iterator position, T&& x) {
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);
354 void insert(iterator position, std::initializer_list<T> l) {
355 insert(position, l.begin(), l.end());
358 void insert(iterator position, size_type n,
const T& x) {
359 link_type
prev = position.node_->prev_;
361 link_type temp = this->create_node(x);
363 temp->next_ =
prev->next_;
364 prev->next_->prev_ = temp;
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_);
380 iterator erase(iterator first, iterator last)
noexcept {
381 while (first != last) first = erase(first);
384 void clear() noexcept {
385 link_type cur = head_->next_;
386 while (cur != head_) {
387 link_type temp = cur;
392 head_->prev_ = head_;
393 head_->next_ = head_;
396 void swap(list& x)
noexcept {
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;
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);
420 void remove(
const T& x) {
421 return this->remove_if([&](
const T& oth) ->
bool {
return oth == x; });
424 void splice(iterator position, list& x) {
426 transfer(position, x.begin(), x.end());
428 void splice(iterator position, list&, iterator i) {
431 if (i == position || j == position)
return;
432 transfer(position, i, j);
434 void splice(iterator position, list&, iterator first, iterator last) {
435 if (first != last) transfer(position, first, last);
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)) {
447 iterator temp = first2;
449 transfer(first1, first2, temp);
453 if (first2 != last2) {
454 transfer(last1, first2, last2);
457 void merge(list& x) {
458 this->merge(x,
_MSTL less<T>());
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)) {
469 iterator temp = first2;
471 transfer(first1, first2, temp);
475 if (first2 != last2) {
476 transfer(last1, first2, last2);
480 void merge(list&& x) {
484 void reverse() noexcept {
486 link_type current = head_;
488 _MSTL swap(current->prev_, current->next_);
489 current = current->prev_;
490 }
while (current != head_);
493 template <
typename Pred>
494 void unique(Pred pred)
noexcept {
496 iterator current = begin();
497 iterator
next = current;
498 while (++
next != end()) {
499 if (pred(*current, *
next)) {
507 void unique() noexcept {
508 unique(
_MSTL equal_to<T>());
511 template <
typename Pred>
512 void sort(Pred pred) {
514 link_type p = head_->next_->next_;
517 link_type
prev = p->prev_;
518 while (
prev != head_ && pred(temp,
prev->data_)) {
522 prev->next_->data_ = temp;
527 sort(
_MSTL less<T>());
530 MSTL_NODISCARD const_reference at(size_type position)
const {
531 const_iterator iter = cbegin();
532 while (position--) ++iter;
533 return iter.node_->data_;
535 MSTL_NODISCARD reference at(
const size_type position) {
536 return const_cast<reference
>(
537 static_cast<const list*
>(
this)->at(position)
540 MSTL_NODISCARD const_reference operator [](
const size_type position)
const {
541 return this->at(position);
543 MSTL_NODISCARD reference operator [](
const size_type position) {
544 return this->at(position);
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());
552 MSTL_NODISCARD
bool operator <(
const list& rhs)
const
557#if MSTL_SUPPORT_DEDUCTION_GUIDES__
558template <
typename Iterator,
typename Alloc>
559list(Iterator, Iterator, Alloc = Alloc()) -> list<iter_value_t<Iterator>, Alloc>;
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
void swap()=delete
删除无参数的swap重载
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名