1#ifndef MSTL_CORE_CONTAINER_MULTIMAP_HPP__
2#define MSTL_CORE_CONTAINER_MULTIMAP_HPP__
6template <
typename Key,
typename T,
typename Compare = less<Key>,
7 typename Alloc = allocator<rb_tree_node<pair<const Key, T>>>>
8class multimap :
public icollector<multimap<Key, T, Compare, Alloc>> {
9#ifdef MSTL_STANDARD_20__
10 static_assert(is_allocator_v<Alloc>,
"Alloc type is not a standard allocator type.");
12 static_assert(is_same_v<rb_tree_node<pair<const Key, T>>,
typename Alloc::value_type>,
13 "allocator type mismatch.");
14 static_assert(is_object_v<T>,
"multimap only contains object types.");
16 using base_type = rb_tree<Key, pair<const Key, T>, select1st<pair<const Key, T>>, Compare, Alloc>;
21 using mapped_type = T;
22 using value_type = pair<const Key, T>;
23 using key_compare = Compare;
25 struct value_compare {
28 friend class multimap;
31 bool operator ()(
const value_type& x,
const value_type& y)
const noexcept {
32 return comp_(x.first, y.first);
37 using size_type =
typename base_type::size_type;
38 using difference_type =
typename base_type::difference_type;
39 using pointer =
typename base_type::pointer;
40 using const_pointer =
typename base_type::const_pointer;
41 using reference =
typename base_type::reference;
42 using const_reference =
typename base_type::const_reference;
44 using iterator =
typename base_type::iterator;
45 using const_iterator =
typename base_type::const_iterator;
46 using reverse_iterator =
typename base_type::reverse_iterator;
47 using const_reverse_iterator =
typename base_type::const_reverse_iterator;
49 using allocator_type =
typename base_type::allocator_type;
54 template <
typename Key1,
typename T1,
typename Compare1,
typename Alloc1>
55 friend bool operator ==(
const multimap<Key1, T1, Compare1, Alloc1>&,
56 const multimap<Key1, T1, Compare1, Alloc1>&)
noexcept;
57 template <
typename Key1,
typename T1,
typename Compare1,
typename Alloc1>
58 friend bool operator <(
const multimap<Key1, T1, Compare1, Alloc1>&,
59 const multimap<Key1, T1, Compare1, Alloc1>&)
noexcept;
62 multimap() : tree_(Compare()) {}
63 explicit multimap(
const key_compare& comp) : tree_(comp) {}
65 multimap(
const multimap& x) : tree_(x.tree_) {}
67 multimap& operator =(
const multimap& x) =
default;
69 multimap(multimap&& x)
noexcept(is_nothrow_move_constructible_v<base_type>)
72 multimap& operator =(multimap&& x)
noexcept(
noexcept(
swap(x))) {
77 template <
typename Iterator>
78 multimap(Iterator first, Iterator last) : tree_(Compare()) {
79 tree_.insert_equal(first, last);
81 template <
typename Iterator>
82 multimap(Iterator first, Iterator last,
const key_compare& comp) : tree_(comp) {
83 tree_.insert_equal(first, last);
86 multimap(std::initializer_list<value_type> l) : multimap(l.
begin(), l.
end()) {}
87 multimap(std::initializer_list<value_type> l,
const key_compare& comp) : multimap(l.
begin(), l.
end(), comp) {}
89 multimap& operator =(std::initializer_list<value_type> l) {
91 insert(l.begin(), l.end());
94 ~multimap() =
default;
96 MSTL_NODISCARD iterator
begin() noexcept {
return tree_.begin(); }
97 MSTL_NODISCARD iterator
end() noexcept {
return tree_.end(); }
98 MSTL_NODISCARD const_iterator
begin() const noexcept {
return tree_.cbegin(); }
99 MSTL_NODISCARD const_iterator
end() const noexcept {
return tree_.cend(); }
100 MSTL_NODISCARD const_iterator
cbegin() const noexcept {
return tree_.cbegin(); }
101 MSTL_NODISCARD const_iterator
cend() const noexcept {
return tree_.cend(); }
102 MSTL_NODISCARD reverse_iterator
rbegin() noexcept {
return tree_.rbegin(); }
103 MSTL_NODISCARD reverse_iterator
rend() noexcept {
return tree_.rend(); }
104 MSTL_NODISCARD const_reverse_iterator
rbegin() const noexcept {
return tree_.rbegin(); }
105 MSTL_NODISCARD const_reverse_iterator
rend() const noexcept {
return tree_.rend(); }
106 MSTL_NODISCARD const_reverse_iterator
crbegin() const noexcept {
return tree_.crbegin(); }
107 MSTL_NODISCARD const_reverse_iterator
crend() const noexcept {
return tree_.crend(); }
109 MSTL_NODISCARD size_type
size() const noexcept {
return tree_.size(); }
110 MSTL_NODISCARD size_type max_size() const noexcept {
return tree_.max_size(); }
111 MSTL_NODISCARD
bool empty() const noexcept {
return tree_.empty(); }
113 MSTL_NODISCARD allocator_type get_allocator() const noexcept {
return allocator_type(); }
115 MSTL_NODISCARD key_compare key_comp() const noexcept {
return tree_.key_comp(); }
116 MSTL_NODISCARD value_compare value_comp() const noexcept {
return value_compare(tree_.key_comp()); }
118 template <
typename... Args>
119 iterator emplace(Args&&... args) {
122 iterator insert(
const value_type& x) {
123 return tree_.insert_equal(x);
125 iterator insert(value_type&& x) {
126 return tree_.insert_equal(
_MSTL move(x));
129 template <
typename... Args>
130 iterator emplace_hint(iterator position, Args&&... args) {
133 iterator insert(iterator position,
const value_type& x) {
134 return tree_.insert_equal(position, x);
136 iterator insert(iterator position, value_type&& x) {
137 return tree_.insert_equal(position,
_MSTL move(x));
140 template <
typename Iterator>
141 void insert(Iterator first, Iterator last) {
142 tree_.insert_equal(first, last);
145 void erase(iterator position)
noexcept { tree_.erase(position); }
146 size_type
erase(
const key_type& x)
noexcept {
return tree_.erase(x); }
147 void erase(iterator first, iterator last)
noexcept { tree_.erase(first, last); }
149 void clear() noexcept { tree_.clear(); }
151 MSTL_NODISCARD iterator
find(
const key_type& x) {
return tree_.find(x); }
152 MSTL_NODISCARD const_iterator
find(
const key_type& x)
const {
return tree_.find(x); }
153 MSTL_NODISCARD size_type
count(
const key_type& x)
const {
return tree_.count(x); }
155 MSTL_NODISCARD iterator
lower_bound(
const key_type& x) {
return tree_.lower_bound(x); }
156 MSTL_NODISCARD const_iterator
lower_bound(
const key_type& x)
const {
return tree_.lower_bound(x); }
157 MSTL_NODISCARD iterator
upper_bound(
const key_type& x) {
return tree_.upper_bound(x); }
158 MSTL_NODISCARD const_iterator
upper_bound(
const key_type& x)
const {
return tree_.upper_bound(x); }
160 MSTL_NODISCARD pair<iterator, iterator>
equal_range(
const key_type& x) {
return tree_.equal_range(x); }
161 MSTL_NODISCARD pair<const_iterator, const_iterator>
equal_range(
const key_type& x)
const {
162 return tree_.equal_range(x);
165 void swap(multimap& x)
noexcept(
noexcept(tree_.swap(x.tree_))) { tree_.swap(x.tree_); }
167 MSTL_NODISCARD
bool operator ==(
const multimap& rhs)
const
168 noexcept(
noexcept(tree_ == rhs.tree_)) {
169 return tree_ == rhs.tree_;
171 MSTL_NODISCARD
bool operator <(
const multimap& rhs)
const
172 noexcept(
noexcept(tree_ < rhs.tree_)) {
173 return tree_ < rhs.tree_;
176#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
177template <
typename Iterator,
typename Compare,
typename Alloc
179multimap(Iterator, Iterator, Compare = Compare(), Alloc = Alloc()) ->
182template <
typename Key,
typename T,
typename Compare = less<Key>,
typename Alloc
183 = allocator<pair<const Key, T>>>
184multimap(std::initializer_list<
pair<Key, T>>, Compare = Compare(), Alloc = Alloc())
185-> multimap<Key, T, Compare, Alloc>;
187template <
typename Iterator,
typename Alloc>
188multimap(Iterator, Iterator, Alloc) ->
191template <
typename Key,
typename T,
typename Alloc>
192multimap(std::initializer_list<
pair<Key, T>>, Alloc) -> multimap<Key, T, 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
等于空指针比较
remove_const_t< typename iter_value_t< Iterator >::first_type > iter_map_key_t
从映射迭代器中提取键类型
typename iter_value_t< Iterator >::second_type iter_map_value_t
从映射迭代器中提取值类型
standard_allocator< T > allocator
标准分配器别名
#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反向结束迭代器
MSTL_NODISCARD constexpr bool operator==(const T &rhs) const noexcept(noexcept(derived()==rhs))
相等比较运算符
MSTL_NODISCARD constexpr bool operator<(const T &rhs) const noexcept(noexcept(derived()< rhs))
小于比较运算符