1#ifndef MSTL_CORE_CONTAINER_RB_TREE_HPP__
2#define MSTL_CORE_CONTAINER_RB_TREE_HPP__
11MSTL_INLINE17
constexpr bool RB_TREE_RED =
false;
12MSTL_INLINE17
constexpr bool RB_TREE_BLACK =
true;
15struct __rb_tree_node_base;
16struct __rb_tree_base_iterator;
19template <
bool IsConst,
typename RB_TREE>
20struct rb_tree_iterator;
21template <
typename Key,
typename Value,
typename KeyOfValue,
typename Compare,
typename Alloc>
26MSTL_API
void rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
noexcept;
27MSTL_API
void rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)
noexcept;
28MSTL_API
void rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
noexcept;
29MSTL_API __rb_tree_node_base* rb_tree_rebalance_for_erase(
30 __rb_tree_node_base* z, __rb_tree_node_base*& root,
31 __rb_tree_node_base*& leftmost, __rb_tree_node_base*& rightmost
35struct MSTL_API __rb_tree_node_base {
37 using color_type = bool;
40 using base_ptr = __rb_tree_node_base*;
42 color_type color_ = RB_TREE_RED;
43 base_ptr parent_ =
nullptr;
44 base_ptr left_ =
nullptr;
45 base_ptr right_ =
nullptr;
47 friend _INNER __rb_tree_base_iterator;
48 template <
bool,
typename>
friend struct _MSTL rb_tree_iterator;
49 template <
typename,
typename,
typename,
typename,
typename>
friend class _MSTL rb_tree;
50 friend MSTL_API
void _INNER rb_tree_rotate_left(__rb_tree_node_base*, __rb_tree_node_base*&)
noexcept;
51 friend MSTL_API
void _INNER rb_tree_rotate_right(__rb_tree_node_base*, __rb_tree_node_base*&)
noexcept;
52 friend MSTL_API
void _INNER rb_tree_rebalance(__rb_tree_node_base*, __rb_tree_node_base*&)
noexcept;
53 friend MSTL_API
_INNER __rb_tree_node_base*
_INNER rb_tree_rebalance_for_erase(
54 _INNER __rb_tree_node_base*,
_INNER __rb_tree_node_base*&,
55 _INNER __rb_tree_node_base*&,
_INNER __rb_tree_node_base*&)
noexcept;
57 static base_ptr minimum(base_ptr x)
noexcept {
58 while (x->left_ !=
nullptr) x = x->left_;
61 static base_ptr maximum(base_ptr x)
noexcept {
62 while (x->right_ !=
nullptr) x = x->right_;
71struct rb_tree_node :
_INNER __rb_tree_node_base {
75 template <
typename,
typename,
typename,
typename,
typename>
friend class rb_tree;
76 template <
bool,
typename>
friend struct rb_tree_iterator;
79 rb_tree_node() =
default;
80 ~rb_tree_node() =
default;
85struct MSTL_API __rb_tree_base_iterator {
87 using iterator_category = bidirectional_iterator_tag;
90 using base_ptr = __rb_tree_node_base::base_ptr;
91 base_ptr node_ =
nullptr;
93 void increment() noexcept;
94 void decrement() noexcept;
97 MSTL_NODISCARD
bool operator ==(const __rb_tree_base_iterator& rhs) const noexcept {
98 return node_ == rhs.node_;
100 MSTL_NODISCARD
bool operator !=(
const __rb_tree_base_iterator& rhs)
const noexcept {
101 return node_ != rhs.node_;
107template <
bool IsConst,
typename RB_TREE>
108struct rb_tree_iterator :
_INNER __rb_tree_base_iterator {
110 using container_type = RB_TREE;
111 using iterator = rb_tree_iterator<false, container_type>;
112 using const_iterator = rb_tree_iterator<true, container_type>;
115 using value_type =
typename container_type::value_type;
118 using difference_type =
typename container_type::difference_type;
119 using size_type =
typename container_type::size_type;
122 using link_type = rb_tree_node<value_type>*;
124 const container_type* tree_ =
nullptr;
126 template <
typename,
typename,
typename,
typename,
typename>
friend class rb_tree;
127 template <
bool,
typename>
friend struct rb_tree_iterator;
130 rb_tree_iterator() =
default;
131 rb_tree_iterator(link_type x,
const container_type* cont)
136 rb_tree_iterator(
const iterator& it) {
140 rb_tree_iterator& operator =(
const iterator& it) {
147 rb_tree_iterator(iterator&& it)
noexcept {
153 rb_tree_iterator& operator =(iterator&& it) {
162 rb_tree_iterator(
const const_iterator& it) {
166 rb_tree_iterator& operator =(
const const_iterator& it) {
173 rb_tree_iterator(const_iterator&& it) {
179 rb_tree_iterator& operator =(const_iterator&& it) {
188 ~rb_tree_iterator() =
default;
190 MSTL_NODISCARD reference
operator *() const noexcept {
191 MSTL_DEBUG_VERIFY(node_ && tree_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(rb_tree_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
192 link_type link = link_type(node_);
193 MSTL_DEBUG_VERIFY(node_ != tree_->header_ && node_->parent_ !=
nullptr,
194 __MSTL_DEBUG_MESG_OUT_OF_RANGE(rb_tree_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
197 MSTL_NODISCARD pointer operator ->() const noexcept {
201 rb_tree_iterator& operator ++() noexcept {
202 MSTL_DEBUG_VERIFY(node_ && tree_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(rb_tree_iterator, __MSTL_DEBUG_TAG_INCREMENT));
203 MSTL_DEBUG_VERIFY(link_type(node_) != tree_->header_,
204 __MSTL_DEBUG_MESG_OUT_OF_RANGE(rb_tree_iterator, __MSTL_DEBUG_TAG_INCREMENT));
208 rb_tree_iterator operator ++(
int)
noexcept {
209 rb_tree_iterator tmp = *
this;
213 rb_tree_iterator& operator --() noexcept {
214 MSTL_DEBUG_VERIFY(node_ && tree_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(rb_tree_iterator, __MSTL_DEBUG_TAG_DECREMENT));
215 MSTL_DEBUG_VERIFY(node_ != tree_->header_,
216 __MSTL_DEBUG_MESG_OUT_OF_RANGE(rb_tree_iterator, __MSTL_DEBUG_TAG_DECREMENT));
220 rb_tree_iterator operator --(
int)
noexcept {
221 rb_tree_iterator tmp = *
this;
226 MSTL_NODISCARD
bool operator ==(
const rb_tree_iterator& rhs)
const noexcept {
227 MSTL_DEBUG_VERIFY(node_ && tree_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(rb_tree_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
228 MSTL_DEBUG_VERIFY(tree_ == rhs.tree_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(rb_tree_iterator));
229 return __rb_tree_base_iterator::operator ==(rhs);
231 MSTL_NODISCARD
bool operator !=(
const rb_tree_iterator& rhs)
const noexcept {
232 MSTL_DEBUG_VERIFY(node_ && tree_, __MSTL_DEBUG_MESG_OPERATE_NULLPTR(rb_tree_iterator, __MSTL_DEBUG_TAG_DEREFERENCE));
233 MSTL_DEBUG_VERIFY(tree_ == rhs.tree_, __MSTL_DEBUG_MESG_CONTAINER_INCOMPATIBLE(rb_tree_iterator));
234 return __rb_tree_base_iterator::operator !=(rhs);
237 MSTL_NODISCARD
constexpr pointer base() const noexcept {
243template <
typename Key,
typename Value,
typename KeyOfValue,
typename Compare,
245class rb_tree :
icollector<rb_tree<Key, Value, KeyOfValue, Compare, Alloc>> {
246#ifdef MSTL_STANDARD_20__
247 static_assert(is_allocator_v<Alloc>,
"Alloc type is not a standard allocator type.");
249 static_assert(is_same_v<rb_tree_node<Value>,
typename Alloc::value_type>,
"allocator type mismatch.");
250 static_assert(is_object_v<Value>,
"list only contains object types.");
252 using base_node =
_INNER __rb_tree_node_base;
253 using link_node = rb_tree_node<Value>;
254 using base_ptr = base_node*;
255 using link_type = link_node*;
258 using key_type = Key;
259 using color_type = bool;
263 using iterator = rb_tree_iterator<false, rb_tree>;
264 using const_iterator = rb_tree_iterator<true, rb_tree>;
265 using reverse_iterator =
_MSTL reverse_iterator<iterator>;
266 using const_reverse_iterator =
_MSTL reverse_iterator<const_iterator>;
268 using allocator_type = Alloc;
271 link_type header_ =
nullptr;
272 Compare key_compare_{};
273 KeyOfValue extracter_{};
274 compressed_pair<allocator_type, size_t> size_pair_{ default_construct_tag{}, 0 };
276 template <
bool,
typename>
friend struct rb_tree_iterator;
279 template <
typename... Args>
280 link_type create_node(Args... args) {
281 link_type tmp = size_pair_.
get_base().allocate();
286 throw_exception(memory_exception(
"rb tree construct node failed."));
290 link_type copy_node(link_type x) {
291 link_type tmp = (create_node)(x->data_);
292 tmp->color_ = x->color_;
293 tmp->left_ =
nullptr;
294 tmp->right_ =
nullptr;
297 void destroy_node(link_type p)
noexcept {
298 if (p ==
nullptr)
return;
300 size_pair_.
get_base().deallocate(p);
303 link_type& root() const noexcept {
return reinterpret_cast<link_type&
>(header_->parent_); }
304 link_type& leftmost() const noexcept {
return reinterpret_cast<link_type&
>(header_->left_); }
305 link_type& rightmost() const noexcept {
return reinterpret_cast<link_type&
>(header_->right_); }
307 static link_type& left(link_type x)
noexcept {
return reinterpret_cast<link_type&
>(x->left_); }
308 static link_type& right(link_type x)
noexcept {
return reinterpret_cast<link_type&
>(x->right_); }
309 static link_type& parent(link_type x)
noexcept {
return reinterpret_cast<link_type&
>(x->parent_); }
310 static const Key& key(link_type x)
noexcept {
return KeyOfValue()(x->data_); }
311 static const Key& key(
const base_ptr x)
noexcept {
return rb_tree::key(
reinterpret_cast<link_type
>(x)); }
313 static link_type minimum(link_type x)
noexcept {
314 return static_cast<link_type
>(base_node::minimum(x));
316 static link_type maximum(link_type x)
noexcept {
317 return static_cast<link_type
>(base_node::maximum(x));
320 iterator insert_node_into(base_ptr bx, base_ptr by, link_type p) {
321 auto x =
static_cast<link_type
>(bx);
322 auto y =
static_cast<link_type
>(by);
323 if (y == header_ || x !=
nullptr || key_compare_(key(p), key(y))) {
330 else if (y == leftmost()) leftmost() = p;
334 if (y == rightmost()) rightmost() = p;
339 _INNER rb_tree_rebalance(p, header_->parent_);
341 return iterator(p,
this);
344 link_type copy_under_node(link_type x, link_type parent) {
345 link_type top = copy_node(x);
346 top->parent_ = parent;
348 if (x->right_ !=
nullptr)
349 top->right_ = copy_under_node(right(x), top);
352 while (x !=
nullptr) {
353 link_type y = copy_node(x);
356 if (x->right_ !=
nullptr)
357 y->right_ = copy_under_node(right(x), y);
361 if (root() !=
nullptr) {
362 leftmost() = minimum(root());
363 rightmost() = maximum(root());
365 leftmost() = header_;
366 rightmost() = header_;
369 this->erase_under_node(top);
375 void erase_under_node(link_type x)
noexcept {
376 if (x ==
nullptr)
return;
377 this->erase_under_node(this->right(x));
378 this->erase_under_node(this->left(x));
379 this->destroy_node(x);
383 header_ = size_pair_.
get_base().allocate();
384 header_->color_ = RB_TREE_RED;
386 leftmost() = header_;
387 rightmost() = header_;
390 void copy_from(
const rb_tree& x) {
391 if (x.root() ==
nullptr) {
393 leftmost() = header_;
394 rightmost() = header_;
398 root() = copy_under_node(x.root(), header_);
401 size_pair_.
get_base().deallocate(header_);
404 leftmost() = minimum(root());
405 rightmost() = maximum(root());
407 size_pair_.
value = x.size_pair_.value;
410 pair<iterator, bool> insert_unique_node(link_type p) {
411 link_type y = header_;
412 link_type x = root();
414 while (x !=
nullptr) {
416 comp = key_compare_(key(p), key(x));
417 x = comp ? left(x) : right(x);
422 return pair<iterator, bool>(insert_node_into(x, y, p),
true);
425 if (key_compare_(key(link_type(j.node_)), key(p)))
426 return pair<iterator, bool>(insert_node_into(x, y, p),
true);
428 return pair<iterator, bool>(j,
false);
431 iterator insert_equal_node(link_type p) {
432 link_type y = header_;
433 link_type x = root();
434 while (x !=
nullptr) {
436 x = key_compare_(key(p), key(x)) ? left(x) : right(x);
438 return insert_node_into(x, y, p);
446 explicit rb_tree(
const Compare& comp) : key_compare_(comp) {
450 rb_tree(
const rb_tree& x) :
451 key_compare_(x.key_compare_),
452 extracter_(x.extracter_), size_pair_(x.size_pair_) {
456 rb_tree& operator =(
const rb_tree& x) {
463 rb_tree(rb_tree&& x) noexcept :
467 x.size_pair_.value = 0;
470 rb_tree& operator =(rb_tree&& x)
noexcept {
473 size_pair_.
get_base().deallocate(header_);
475 key_compare_ =
_MSTL move(x.key_compare_);
478 x.size_pair_.value = 0;
485 size_pair_.
get_base().deallocate(header_);
489 MSTL_NODISCARD iterator
begin() noexcept {
return {leftmost(),
this}; }
490 MSTL_NODISCARD iterator
end() noexcept {
return {header_,
this}; }
491 MSTL_NODISCARD const_iterator
begin() const noexcept {
return cbegin(); }
492 MSTL_NODISCARD const_iterator
end() const noexcept {
return cend(); }
493 MSTL_NODISCARD const_iterator
cbegin() const noexcept {
return {leftmost(),
this}; }
494 MSTL_NODISCARD const_iterator
cend() const noexcept {
return {header_,
this}; }
495 MSTL_NODISCARD reverse_iterator
rbegin() noexcept {
return reverse_iterator(
end()); }
496 MSTL_NODISCARD reverse_iterator
rend() noexcept {
return reverse_iterator(
begin()); }
497 MSTL_NODISCARD const_reverse_iterator
rbegin() const noexcept {
return crbegin(); }
498 MSTL_NODISCARD const_reverse_iterator
rend() const noexcept {
return crend(); }
499 MSTL_NODISCARD const_reverse_iterator
crbegin() const noexcept {
return const_reverse_iterator(
cend()); }
500 MSTL_NODISCARD const_reverse_iterator
crend() const noexcept {
return const_reverse_iterator(
cbegin()); }
502 MSTL_NODISCARD size_type
size() const noexcept {
return size_pair_.
value; }
503 MSTL_NODISCARD size_type max_size() const noexcept {
return static_cast<size_type
>(-1); }
504 MSTL_NODISCARD
bool empty() const noexcept {
return size_pair_.
value == 0; }
506 MSTL_NODISCARD allocator_type get_allocator() const noexcept {
return allocator_type(); }
508 MSTL_NODISCARD Compare key_comp() const noexcept(is_nothrow_copy_constructible_v<Compare>) {
512 template <
typename... Args>
513 pair<iterator, bool> emplace_unique(Args&&... args) {
515 return (insert_unique_node)(tmp);
517 pair<iterator, bool> insert_unique(
const value_type& v) {
518 return (emplace_unique)(v);
520 pair<iterator, bool> insert_unique(value_type&& v) {
523 template <
typename... Args>
524 iterator emplace_unique_hint(iterator position, Args&&... args) {
526 if (position.node_ == header_->left_) {
527 if (
size() > 0 && key_compare_(key(tmp), key(position.node_)))
528 return insert_node_into(position.node_, position.node_, tmp);
529 return insert_unique_node(tmp).first;
531 if (position.node_ == header_) {
532 if (key_compare_(key(rightmost()), key(tmp)))
533 return insert_node_into(
nullptr, rightmost(), tmp);
534 return insert_unique_node(tmp).first;
536 iterator before = position;
538 if (key_compare_(key(before.node_), key(tmp)) &&
539 key_compare_(key(tmp), key(position.node_))) {
540 if (right(link_type(before.node_)) ==
nullptr)
541 return insert_node_into(
nullptr, before.node_, tmp);
542 return insert_node_into(position.node_, position.node_, tmp);
544 return insert_unique_node(tmp).first;
546 iterator insert_unique(iterator position,
const value_type& v) {
547 return (emplace_unique_hint)(position, v);
549 iterator insert_unique(iterator position, value_type&& v) {
550 return (emplace_unique_hint)(position,
_MSTL move(v));
552 template <
typename Iterator, enable_if_t<is_ranges_input_iter_v<Iterator>,
int> = 0>
553 void insert_unique(Iterator first, Iterator last) {
554 for (; first != last; ++first) insert_unique(*first);
557 template <
typename... Args>
558 iterator emplace_equal(Args&&... args) {
560 return (insert_equal_node)(tmp);
562 iterator insert_equal(
const value_type& v) {
563 return (emplace_equal)(v);
565 iterator insert_equal(value_type&& v) {
568 template <
typename... Args>
569 iterator emplace_equal_hint(iterator position, Args&&... args) {
571 if (position.node_ == header_->left_) {
572 if (
size() > 0 && key_compare_(key(tmp), key(position.node_)))
573 return insert_node_into(position.node_, position.node_, tmp);
574 return insert_equal_node(tmp);
576 if (position.node_ == header_) {
577 if (!key_compare_(key(tmp), key(rightmost())))
578 return insert_node_into(
nullptr, rightmost(), tmp);
579 return insert_equal_node(tmp);
581 iterator before = position;
583 if (!key_compare_(key(tmp), key(before.node_)) &&
584 !key_compare_(key(position.node_), key(tmp))) {
585 if (right(link_type(before.node_)) ==
nullptr)
586 return insert_node_into(
nullptr, before.node_, tmp);
587 return insert_node_into(position.node_, position.node_, tmp);
589 return insert_equal_node(tmp);
591 iterator insert_equal(iterator position,
const value_type& v) {
592 return (emplace_equal_hint)(position, v);
594 iterator insert_equal(iterator position, value_type&& v) {
595 return (emplace_equal_hint)(position,
_MSTL move(v));
597 template <
typename Iterator, enable_if_t<is_ranges_input_iter_v<Iterator>,
int> = 0>
598 void insert_equal(Iterator first, Iterator last) {
599 for (; first != last; ++first) insert_equal(*first);
602 size_type
erase(
const key_type& k)
noexcept {
608 void erase(iterator position)
noexcept {
609 auto y =
reinterpret_cast<link_type
>(rb_tree_rebalance_for_erase(
610 position.node_, header_->parent_, header_->left_, header_->right_));
614 void erase(iterator first, iterator last)
noexcept {
615 if (first ==
begin() && last ==
end())
618 while (first != last)
erase(first++);
621 void clear() noexcept {
622 if (size_pair_.
value == 0)
return;
623 this->erase_under_node(root());
624 leftmost() = header_;
626 rightmost() = header_;
627 size_pair_.
value = 0;
630 MSTL_NODISCARD iterator
find(
const key_type& k) {
631 link_type y = header_;
632 link_type x = root();
633 while (x !=
nullptr) {
634 if (!key_compare_(key(x), k)) {
643 return key_compare_(k, key(y)) ?
end() : j;
645 MSTL_NODISCARD const_iterator
find(
const key_type& k)
const {
646 link_type y = header_;
647 link_type x = root();
648 while (x !=
nullptr) {
649 if (!key_compare_(key(x), k)) {
655 const_iterator j(y,
this);
658 return key_compare_(k, key(y)) ?
cend() : j;
661 MSTL_NODISCARD size_type
count(
const key_type& k)
const {
662 pair<const_iterator, const_iterator> p =
equal_range(k);
667 MSTL_NODISCARD iterator
lower_bound(
const key_type& k) {
668 link_type y = header_;
669 link_type x = root();
670 while (x !=
nullptr) {
671 if (!key_compare_(key(x), k)) {
677 return iterator(y,
this);
679 MSTL_NODISCARD const_iterator
lower_bound(
const key_type& k)
const {
680 link_type y = header_;
681 link_type x = root();
682 while (x !=
nullptr) {
683 if (!key_compare_(key(x), k)) {
689 return const_iterator(y,
this);
692 MSTL_NODISCARD iterator
upper_bound(
const key_type& k) {
693 link_type y = header_;
694 link_type x = root();
695 while (x !=
nullptr) {
696 if (key_compare_(k, key(x))) {
702 return iterator(y,
this);
704 MSTL_NODISCARD const_iterator
upper_bound(
const key_type& k)
const {
705 link_type y = header_;
706 link_type x = root();
707 while (x !=
nullptr) {
708 if (key_compare_(k, key(x))) {
714 return const_iterator(y,
this);
717 MSTL_NODISCARD pair<iterator, iterator>
equal_range(
const key_type& k) {
720 MSTL_NODISCARD pair<const_iterator, const_iterator>
equal_range(
const key_type& k)
const {
724 void swap(rb_tree& x)
725 noexcept(is_nothrow_swappable_v<Compare> &&
726 is_nothrow_swappable_v<KeyOfValue> &&
727 noexcept(size_pair_.
swap(x.size_pair_))) {
730 _MSTL swap(key_compare_, x.key_compare_);
734 MSTL_NODISCARD
bool operator ==(
const rb_tree& rhs)
const
738 MSTL_NODISCARD
bool operator <(
const rb_tree& rhs)
const
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr Iterator lower_bound(Iterator first, Iterator last, const T &value, Compare comp)
查找有序范围中第一个不小于指定值的元素位置
constexpr Iterator upper_bound(Iterator first, Iterator last, const T &value, Compare comp)
查找有序范围中第一个大于指定值的元素位置
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 pair< Iterator, Iterator > equal_range(Iterator first, Iterator last, const T &value, Compare comp)
查找值的相等范围
constexpr iter_difference_t< Iterator > count(Iterator first, Iterator last, const T &value)
统计范围内等于指定值的元素数量
constexpr duration< _INNER __common_rep_t< Rep1, Rep2 >, Period > operator*(const duration< Rep1, Period > &value, const Rep2 &scalar)
乘法运算符(持续时间 * 标量)
MSTL_NODISCARD constexpr Iterator find(Iterator first, Iterator last, const T &value)
查找范围内第一个等于指定值的元素
bool operator!=(const function< Res(Args...)> &f, nullptr_t null) noexcept
不等于空指针比较
bool operator==(const function< Res(Args...)> &f, nullptr_t null) noexcept
等于空指针比较
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 iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
standard_allocator< T > allocator
标准分配器别名
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
MSTL_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
constexpr size_t erase(Container &cont, const U &value)
从容器中删除所有等于指定值的元素
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
void swap()=delete
删除无参数的swap重载
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr bool empty(const Container &cont) noexcept(noexcept(cont.empty()))
检查容器是否为空
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) rend(Container &cont) noexcept(noexcept(cont.rend()))
获取const容器的反向起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) cend(const Container &cont) noexcept(noexcept(cont.cend()))
获取const容器的const结束迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) begin(Container &cont) noexcept(noexcept(cont.begin()))
获取容器的起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) crbegin(const Container &cont) noexcept(noexcept(cont.crbegin()))
获取const容器的const反向起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) cbegin(const Container &cont) noexcept(noexcept(cont.cbegin()))
获取const容器的const起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) rbegin(Container &cont) noexcept(noexcept(cont.rbegin()))
获取容器的反向起始迭代器
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) crend(const Container &cont) noexcept(noexcept(cont.crend()))
获取const容器的const反向结束迭代器
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
constexpr void swap(compressed_pair &rhs) noexcept(is_nothrow_swappable_v< T >)
交换两个压缩对
constexpr compressed_pair & get_base() noexcept
获取基类引用