1#ifndef MSTL_CORE_CONTAINER_MAP_HPP__
2#define MSTL_CORE_CONTAINER_MAP_HPP__
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.");
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.");
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 {
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;
55 map() : tree_(Compare()) {}
56 explicit map(
const key_compare& comp) : tree_(comp) {}
58 map(
const map& x) : tree_(x.tree_) {}
60 map& operator =(
const map& x) =
default;
62 map(map&& x)
noexcept(is_nothrow_move_constructible_v<base_type>)
65 map& operator =(map&& x)
noexcept(
noexcept(
swap(x))) {
70 template <
typename Iterator>
71 map(Iterator first, Iterator last) : tree_(Compare()) {
72 tree_.insert_unique(first, last);
74 template <
typename Iterator>
75 map(Iterator first, Iterator last,
const key_compare& comp) : tree_(comp) {
76 tree_.insert_unique(first, last);
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) {}
82 map& operator =(std::initializer_list<value_type> l) {
84 insert(l.begin(), l.end());
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(); }
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(); }
106 MSTL_NODISCARD allocator_type get_allocator() const noexcept {
return allocator_type(); }
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()); }
111 template <
typename... Args>
112 pair<iterator, bool> emplace(Args&&... args) {
115 pair<iterator, bool> insert(
const value_type& x) {
116 return tree_.insert_unique(x);
118 pair<iterator, bool> insert(value_type&& x) {
119 return tree_.emplace_unique(
_MSTL move(x));
122 template <
typename... Args>
123 iterator emplace_hint(iterator position, Args&&... args) {
126 iterator insert(iterator position,
const value_type& x) {
127 return tree_.insert_unique(position, x);
129 iterator insert(iterator position, value_type&& x) {
130 return tree_.insert_unique(position,
_MSTL move(x));
133 template <
typename Iterator>
134 void insert(Iterator first, Iterator last) {
135 tree_.insert_unique(first, last);
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); }
142 void clear() noexcept { tree_.clear(); }
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); }
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); }
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);
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());
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());
172 MSTL_NODISCARD
const mapped_type& at(
const key_type& k)
const {
174 if (iter ==
cend() && key_comp()(iter->first, k)) {
175 throw_exception(value_exception(
"the value of this key does not exists."));
179 MSTL_NODISCARD mapped_type& at(
const key_type& k) {
180 return const_cast<mapped_type&
>(
const_cast<const map*
>(
this)->at(k));
183 void swap(map& x)
noexcept(
noexcept(tree_.swap(x.tree_))) { tree_.swap(x.tree_); }
185 MSTL_NODISCARD
bool operator ==(
const map& rhs)
const
186 noexcept(
noexcept(tree_ == rhs.tree_)) {
187 return tree_ == rhs.tree_;
189 MSTL_NODISCARD
bool operator <(
const map& rhs)
const
190 noexcept(
noexcept(tree_ < rhs.tree_)) {
191 return tree_ < rhs.tree_;
194#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
195template <
typename Iterator,
typename Compare,
typename Alloc
197map(Iterator, Iterator, Compare = Compare(), Alloc = Alloc()) ->
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>;
204template <
typename Iterator,
typename Alloc>
205map(Iterator, Iterator, Alloc) ->
208template <
typename Key,
typename T,
typename Alloc>
209map(std::initializer_list<
pair<Key, T>>, Alloc) -> map<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反向结束迭代器