1#ifndef MSTL_CORE_CONTAINER_MULTISET_HPP__
2#define MSTL_CORE_CONTAINER_MULTISET_HPP__
6template <
typename Key,
typename Compare = less<Key>,
typename Alloc = allocator<rb_tree_node<Key>>>
7class multiset :
icollector<multiset<Key, Compare, Alloc>> {
8#ifdef MSTL_STANDARD_20__
9 static_assert(is_allocator_v<Alloc>,
"Alloc type is not a standard allocator type.");
11 static_assert(is_same_v<rb_tree_node<Key>,
typename Alloc::value_type>,
12 "allocator type mismatch.");
13 static_assert(is_object_v<Key>,
"multiset only contains object types.");
15 using base_type = rb_tree<Key, Key, identity<Key>, Compare, Alloc>;
19 using value_type = Key;
20 using key_compare = Compare;
21 using value_compare = Compare;
23 using size_type =
typename base_type::size_type;
24 using difference_type =
typename base_type::difference_type;
25 using pointer =
typename base_type::pointer;
26 using const_pointer =
typename base_type::const_pointer;
27 using reference =
typename base_type::reference;
28 using const_reference =
typename base_type::const_reference;
30 using iterator =
typename base_type::iterator;
31 using const_iterator =
typename base_type::const_iterator;
32 using reverse_iterator =
typename base_type::reverse_iterator;
33 using const_reverse_iterator =
typename base_type::const_reverse_iterator;
35 using allocator_type =
typename base_type::allocator_type;
41 multiset() : tree_(Compare()) {}
42 explicit multiset(
const key_compare& comp) : tree_(comp) {}
44 multiset(
const multiset& x) : tree_(x.tree_) {}
46 multiset& operator =(
const multiset& x) =
default;
48 multiset(multiset&& x)
noexcept(is_nothrow_move_constructible_v<base_type>)
52 multiset& operator =(multiset&& x)
noexcept(
noexcept(
swap(x))) {
57 template <
typename Iterator>
58 multiset(Iterator first, Iterator last) : tree_(Compare()) {
59 tree_.insert_equal(first, last);
61 template <
typename Iterator>
62 multiset(Iterator first, Iterator last,
const key_compare& comp) : tree_(comp) {
63 tree_.insert_equal(first, last);
66 multiset(std::initializer_list<value_type> l) : multiset(l.
begin(), l.
end()) {}
67 multiset(std::initializer_list<value_type> l,
const key_compare& comp) : multiset(l.
begin(), l.
end(), comp) {}
69 multiset& operator =(std::initializer_list<value_type> l) {
71 insert(l.begin(), l.end());
74 ~multiset() =
default;
76 MSTL_NODISCARD iterator
begin() noexcept {
return tree_.begin(); }
77 MSTL_NODISCARD iterator
end() noexcept {
return tree_.end(); }
78 MSTL_NODISCARD const_iterator
cbegin() const noexcept {
return tree_.cbegin(); }
79 MSTL_NODISCARD const_iterator
cend() const noexcept {
return tree_.cend(); }
80 MSTL_NODISCARD reverse_iterator
rbegin() noexcept {
return reverse_iterator(tree_.begin()); }
81 MSTL_NODISCARD reverse_iterator
rend() noexcept {
return reverse_iterator(tree_.end()); }
82 MSTL_NODISCARD const_reverse_iterator
crbegin() const noexcept {
return const_reverse_iterator(tree_.cbegin()); }
83 MSTL_NODISCARD const_reverse_iterator
crend() const noexcept {
return const_reverse_iterator(tree_.cend()); }
85 MSTL_NODISCARD size_type
size() const noexcept {
return tree_.size(); }
86 MSTL_NODISCARD size_type max_size() const noexcept {
return tree_.max_size(); }
87 MSTL_NODISCARD
bool empty() const noexcept {
return tree_.empty(); }
89 MSTL_NODISCARD allocator_type get_allocator() const noexcept {
return allocator_type(); }
91 MSTL_NODISCARD key_compare key_comp() const noexcept {
return tree_.key_comp(); }
92 MSTL_NODISCARD value_compare value_comp() const noexcept {
return value_compare(tree_.key_comp()); }
94 template <
typename... Args>
95 iterator emplace(Args&&... args) {
98 iterator insert(
const value_type& x) {
99 return tree_.insert_equal(x);
101 iterator insert(value_type&& x) {
102 return tree_.insert_equal(
_MSTL move(x));
105 template <
typename... Args>
106 iterator emplace_hint(iterator position, Args&&... args) {
109 iterator insert(iterator position,
const value_type& x) {
110 return tree_.insert_equal(position, x);
112 iterator insert(iterator position, value_type&& x) {
113 return tree_.insert_equal(position,
_MSTL move(x));
116 template <
typename Iterator>
117 void insert(Iterator first, Iterator last) {
118 tree_.insert_equal(first, last);
121 void erase(iterator position)
noexcept { tree_.erase(position); }
122 size_type
erase(
const key_type& x)
noexcept {
return tree_.erase(x); }
123 void erase(iterator first, iterator last)
noexcept { tree_.erase(first, last); }
125 void clear() noexcept { tree_.clear(); }
127 MSTL_NODISCARD iterator
find(
const key_type& x) {
return tree_.find(x); }
128 MSTL_NODISCARD const_iterator
find(
const key_type& x)
const {
return tree_.find(x); }
129 MSTL_NODISCARD size_type
count(
const key_type& x)
const {
return tree_.count(x); }
131 MSTL_NODISCARD iterator
lower_bound(
const key_type& x) {
return tree_.lower_bound(x); }
132 MSTL_NODISCARD const_iterator
lower_bound(
const key_type& x)
const {
return tree_.lower_bound(x); }
133 MSTL_NODISCARD iterator
upper_bound(
const key_type& x) {
return tree_.upper_bound(x); }
134 MSTL_NODISCARD const_iterator
upper_bound(
const key_type& x)
const {
return tree_.upper_bound(x); }
136 MSTL_NODISCARD pair<iterator, iterator>
equal_range(
const key_type& x) {
return tree_.equal_range(x); }
137 MSTL_NODISCARD pair<const_iterator, const_iterator>
equal_range(
const key_type& x)
const {
138 return tree_.equal_range(x);
141 void swap(multiset& x)
noexcept(
noexcept(tree_.swap(x.tree_))) { tree_.swap(x.tree_); }
143 MSTL_NODISCARD
bool operator ==(
const multiset& rhs)
const
144 noexcept(
noexcept(tree_ == rhs.tree_)) {
145 return tree_ == rhs.tree_;
147 MSTL_NODISCARD
bool operator <(
const multiset& rhs)
const
148 noexcept(
noexcept(tree_ < rhs.tree_)) {
149 return tree_ < rhs.tree_;
152#if MSTL_SUPPORT_DEDUCTION_GUIDES__
153template <
typename Iterator,
typename Compare = less<iter_value_t<Iterator>>,
154 typename Alloc = allocator<iter_value_t<Iterator>>>
155multiset(Iterator, Iterator, Compare = Compare(), Alloc = Alloc())
156-> multiset<iter_value_t<Iterator>, Compare, Alloc>;
158template <
typename Key,
typename Compare = less<Key>,
typename Alloc = allocator<Key>>
159multiset(std::initializer_list<Key>, Compare = Compare(), Alloc = Alloc()) -> multiset<Key, Compare, Alloc>;
161template <
typename Iterator,
typename Alloc>
164template <
typename Key,
typename Alloc>
165multiset(std::initializer_list<Key>, Alloc) -> multiset<Key, less<Key>, Alloc>;
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)
查找有序范围中第一个大于指定值的元素位置
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)
统计范围内等于指定值的元素数量
MSTL_NODISCARD constexpr Iterator find(Iterator first, Iterator last, const T &value)
查找范围内第一个等于指定值的元素
bool operator==(const function< Res(Args...)> &f, nullptr_t null) noexcept
等于空指针比较
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
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反向结束迭代器