MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
map.hpp
1#ifndef MSTL_CORE_CONTAINER_MAP_HPP__
2#define MSTL_CORE_CONTAINER_MAP_HPP__
3#include "rb_tree.hpp"
5
6template <typename Key, typename T, typename Compare = less<Key>,
7 typename Alloc = allocator<rb_tree_node<pair<const Key, T>>>>
8class map : public icollector<map<Key, T, Compare, Alloc>> {
9#ifdef MSTL_STANDARD_20__
10 static_assert(is_allocator_v<Alloc>, "Alloc type is not a standard allocator type.");
11#endif
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>, "map only contains object types.");
15
16 using base_type = rb_tree<Key, pair<const Key, T>, select1st<pair<const Key, T>>, Compare, Alloc>;
17
18public:
19 using key_type = Key;
20 using data_type = T;
21 using mapped_type = T;
22 using value_type = pair<const Key, T>;
23 using key_compare = Compare;
24
25 struct value_compare {
26 private:
27 Compare comp_;
28 friend class map;
29
30 public:
31 bool operator ()(const value_type& x, const value_type& y) const noexcept {
32 return comp_(x.first, y.first);
33 }
34 };
35
36public:
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;
43
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;
48
49 using allocator_type = typename base_type::allocator_type;
50
51private:
52 base_type tree_;
53
54public:
55 map() : tree_(Compare()) {}
56 explicit map(const key_compare& comp) : tree_(comp) {}
57
58 map(const map& x) : tree_(x.tree_) {}
59
60 map& operator =(const map& x) = default;
61
62 map(map&& x) noexcept(is_nothrow_move_constructible_v<base_type>)
63 : tree_(_MSTL move(x.tree_)) {}
64
65 map& operator =(map&& x) noexcept(noexcept(swap(x))) {
66 tree_ = _MSTL move(x.tree_);
67 return *this;
68 }
69
70 template <typename Iterator>
71 map(Iterator first, Iterator last) : tree_(Compare()) {
72 tree_.insert_unique(first, last);
73 }
74 template <typename Iterator>
75 map(Iterator first, Iterator last, const key_compare& comp) : tree_(comp) {
76 tree_.insert_unique(first, last);
77 }
78
79 map(std::initializer_list<value_type> l) : map(l.begin(), l.end()) {}
80 map(std::initializer_list<value_type> l, const key_compare& comp) : map(l.begin(), l.end(), comp) {}
81
82 map& operator =(std::initializer_list<value_type> l) {
83 clear();
84 insert(l.begin(), l.end());
85 return *this;
86 }
87 ~map() = default;
88
89 MSTL_NODISCARD iterator begin() noexcept { return tree_.begin(); }
90 MSTL_NODISCARD iterator end() noexcept { return tree_.end(); }
91 MSTL_NODISCARD const_iterator begin() const noexcept { return tree_.cbegin(); }
92 MSTL_NODISCARD const_iterator end() const noexcept { return tree_.cend(); }
93 MSTL_NODISCARD const_iterator cbegin() const noexcept { return tree_.cbegin(); }
94 MSTL_NODISCARD const_iterator cend() const noexcept { return tree_.cend(); }
95 MSTL_NODISCARD reverse_iterator rbegin() noexcept { return tree_.rbegin(); }
96 MSTL_NODISCARD reverse_iterator rend() noexcept { return tree_.rend(); }
97 MSTL_NODISCARD const_reverse_iterator rbegin() const noexcept { return tree_.rbegin(); }
98 MSTL_NODISCARD const_reverse_iterator rend() const noexcept { return tree_.rend(); }
99 MSTL_NODISCARD const_reverse_iterator crbegin() const noexcept { return tree_.crbegin(); }
100 MSTL_NODISCARD const_reverse_iterator crend() const noexcept { return tree_.crend(); }
101
102 MSTL_NODISCARD size_type size() const noexcept { return tree_.size(); }
103 MSTL_NODISCARD size_type max_size() const noexcept { return tree_.max_size(); }
104 MSTL_NODISCARD bool empty() const noexcept { return tree_.empty(); }
105
106 MSTL_NODISCARD allocator_type get_allocator() const noexcept { return allocator_type(); }
107
108 MSTL_NODISCARD key_compare key_comp() const noexcept { return tree_.key_comp(); }
109 MSTL_NODISCARD value_compare value_comp() const noexcept { return value_compare(tree_.key_comp()); }
110
111 template <typename... Args>
112 pair<iterator, bool> emplace(Args&&... args) {
113 return tree_.emplace_unique(_MSTL forward<Args>(args)...);
114 }
115 pair<iterator, bool> insert(const value_type& x) {
116 return tree_.insert_unique(x);
117 }
118 pair<iterator, bool> insert(value_type&& x) {
119 return tree_.emplace_unique(_MSTL move(x));
120 }
121
122 template <typename... Args>
123 iterator emplace_hint(iterator position, Args&&... args) {
124 return tree_.emplace_unique_hint(position, _MSTL forward<Args>(args)...);
125 }
126 iterator insert(iterator position, const value_type& x) {
127 return tree_.insert_unique(position, x);
128 }
129 iterator insert(iterator position, value_type&& x) {
130 return tree_.insert_unique(position, _MSTL move(x));
131 }
132
133 template <typename Iterator>
134 void insert(Iterator first, Iterator last) {
135 tree_.insert_unique(first, last);
136 }
137
138 void erase(iterator position) noexcept { tree_.erase(position); }
139 size_type erase(const key_type& x) noexcept { return tree_.erase(x); }
140 void erase(iterator first, iterator last) noexcept { tree_.erase(first, last); }
141
142 void clear() noexcept { tree_.clear(); }
143
144 MSTL_NODISCARD iterator find(const key_type& x) { return tree_.find(x); }
145 MSTL_NODISCARD const_iterator find(const key_type& x) const { return tree_.find(x); }
146 MSTL_NODISCARD size_type count(const key_type& x) const { return tree_.count(x); }
147
148 MSTL_NODISCARD iterator lower_bound(const key_type& x) { return tree_.lower_bound(x); }
149 MSTL_NODISCARD const_iterator lower_bound(const key_type& x) const { return tree_.lower_bound(x); }
150 MSTL_NODISCARD iterator upper_bound(const key_type& x) { return tree_.upper_bound(x); }
151 MSTL_NODISCARD const_iterator upper_bound(const key_type& x) const { return tree_.upper_bound(x); }
152
153 MSTL_NODISCARD pair<iterator, iterator> equal_range(const key_type& x) { return tree_.equal_range(x); }
154 MSTL_NODISCARD pair<const_iterator, const_iterator> equal_range(const key_type& x) const {
155 return tree_.equal_range(x);
156 }
157
158 MSTL_NODISCARD mapped_type& operator [](const key_type& k) {
159 iterator iter = tree_.lower_bound(k);
160 if (iter == end() || key_comp()(k, iter->first)) {
161 iter = tree_.emplace_unique_hint(iter, k, T());
162 }
163 return iter->second;
164 }
165 MSTL_NODISCARD mapped_type& operator [](key_type&& k) {
166 iterator iter = tree_.lower_bound(k);
167 if (iter == end() || key_comp()(k, iter->first)) {
168 iter = tree_.emplace_unique_hint(iter, _MSTL move(k), T());
169 }
170 return iter->second;
171 }
172 MSTL_NODISCARD const mapped_type& at(const key_type& k) const {
173 const_iterator iter = lower_bound(k);
174 if (iter == cend() && key_comp()(iter->first, k)) {
175 throw_exception(value_exception("the value of this key does not exists."));
176 }
177 return iter->second;
178 }
179 MSTL_NODISCARD mapped_type& at(const key_type& k) {
180 return const_cast<mapped_type&>(const_cast<const map*>(this)->at(k));
181 }
182
183 void swap(map& x) noexcept(noexcept(tree_.swap(x.tree_))) { tree_.swap(x.tree_); }
184
185 MSTL_NODISCARD bool operator ==(const map& rhs) const
186 noexcept(noexcept(tree_ == rhs.tree_)) {
187 return tree_ == rhs.tree_;
188 }
189 MSTL_NODISCARD bool operator <(const map& rhs) const
190 noexcept(noexcept(tree_ < rhs.tree_)) {
191 return tree_ < rhs.tree_;
192 }
193};
194#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
195template <typename Iterator, typename Compare, typename Alloc
197map(Iterator, Iterator, Compare = Compare(), Alloc = Alloc()) ->
199
200template <typename Key, typename T, typename Compare = less<Key>, typename Alloc
201 = allocator<pair<const Key, T>>>
202map(std::initializer_list<pair<Key, T>>, Compare = Compare(), Alloc = Alloc()) -> map<Key, T, Compare, Alloc>;
203
204template <typename Iterator, typename Alloc>
205map(Iterator, Iterator, Alloc) ->
207
208template <typename Key, typename T, typename Alloc>
209map(std::initializer_list<pair<Key, T>>, Alloc) -> map<Key, T, less<Key>, Alloc>;
210#endif
211
213#endif // MSTL_CORE_CONTAINER_MAP_HPP__
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反向结束迭代器
集合器接口模板
小于比较仿函数
存储两个值的元组对