1#ifndef MSTL_CORE_CONTAINER_UNORDERED_MULTIMAP_HPP__
2#define MSTL_CORE_CONTAINER_UNORDERED_MULTIMAP_HPP__
3#include "hashtable.hpp"
6template <
typename Key,
typename T,
typename HashFcn = hash<Key>,
typename EqualKey = equal_to<Key>,
7 typename Alloc = allocator<hashtable_node<pair<const Key, T>>>>
8class unordered_multimap :
icollector<unordered_multimap<Key, T, HashFcn, EqualKey, Alloc>> {
9#ifdef MSTL_STANDARD_20__
10 static_assert(is_hash_v<HashFcn, Key>,
"unordered multimap requires valid hash function.");
11 static_assert(is_allocator_v<Alloc>,
"Alloc type is not a standard allocator type.");
13 static_assert(is_same_v<hashtable_node<pair<const Key, T>>,
typename Alloc::value_type>,
14 "allocator type mismatch.");
15 static_assert(is_object_v<Key>,
"unordered multimap only contains object types.");
17 using base_type = hashtable<pair<const Key, T>, Key, HashFcn, select1st<pair<const Key, T>>, EqualKey, Alloc>;
20 using key_type =
typename base_type::key_type;
21 using value_type =
typename base_type::value_type;
22 using hasher =
typename base_type::hasher;
23 using key_equal =
typename base_type::key_equal;
25 using size_type =
typename base_type::size_type;
26 using difference_type =
typename base_type::difference_type;
27 using pointer =
typename base_type::pointer;
28 using const_pointer =
typename base_type::const_pointer;
29 using reference =
typename base_type::reference;
30 using const_reference =
typename base_type::const_reference;
32 using iterator =
typename base_type::iterator;
33 using const_iterator =
typename base_type::const_iterator;
35 using allocator_type =
typename base_type::allocator_type;
38 base_type ht_{100, hasher(), key_equal()};
40 template <
typename Key1,
typename T1,
typename HashFcn1,
typename EqualKey1,
typename Alloc1>
41 friend bool operator ==(
const unordered_multimap<Key1, T1, HashFcn1, EqualKey1, Alloc1>&,
42 const unordered_multimap<Key1, T1, HashFcn1, EqualKey1, Alloc1>&)
noexcept;
46 unordered_multimap() =
default;
47 explicit unordered_multimap(size_type n) : ht_(n) {}
49 unordered_multimap(size_type n,
const hasher& hf) : ht_(n, hf, key_equal()) {}
50 unordered_multimap(size_type n,
const hasher& hf,
const key_equal& eql) : ht_(n, hf, eql) {}
52 unordered_multimap(
const unordered_multimap& ht) : ht_(ht.ht_) {}
53 unordered_multimap& operator =(
const unordered_multimap& x) =
default;
55 unordered_multimap(unordered_multimap&& x)
noexcept(
noexcept(ht_.swap(x.ht_))) : ht_(
_MSTL forward<base_type>(x.ht_)) {}
56 unordered_multimap& operator =(unordered_multimap&& x)
noexcept(
noexcept(ht_.swap(x.ht_))) {
61 template <
typename Iterator>
62 unordered_multimap(Iterator first, Iterator last) : ht_(100, hasher(), key_equal()) {
63 ht_.insert_equal(first, last);
65 template <
typename Iterator>
66 unordered_multimap(Iterator first, Iterator list, size_type n) : ht_(n, hasher(), key_equal()) {
67 ht_.insert_equal(first, list);
69 template <
typename Iterator>
70 unordered_multimap(Iterator first, Iterator last, size_type n,
const hasher& hf) : ht_(n, hf, key_equal()) {
71 ht_.insert_equal(first, last);
73 template <
typename Iterator>
74 unordered_multimap(Iterator first, Iterator last, size_type n,
const hasher& hf,
const key_equal& eql)
76 ht_.insert_equal(first, last);
79 unordered_multimap(std::initializer_list<value_type> l)
80 : unordered_multimap(l.begin(), l.end()) {}
81 unordered_multimap(std::initializer_list<value_type> l, size_type n)
82 : unordered_multimap(l.begin(), l.end(), n) {}
83 unordered_multimap(std::initializer_list<value_type> l, size_type n,
const hasher& hf)
84 : unordered_multimap(l.begin(), l.end(), n, hf) {}
85 unordered_multimap(std::initializer_list<value_type> l, size_type n,
const hasher& hf,
const key_equal& eql)
86 : unordered_multimap(l.begin(), l.end(), n, hf, eql) {}
88 MSTL_NODISCARD iterator begin() noexcept {
return ht_.begin(); }
89 MSTL_NODISCARD iterator end() noexcept {
return ht_.end(); }
90 MSTL_NODISCARD const_iterator begin() const noexcept {
return ht_.begin(); }
91 MSTL_NODISCARD const_iterator end() const noexcept {
return ht_.end(); }
92 MSTL_NODISCARD const_iterator cbegin() const noexcept {
return ht_.cbegin(); }
93 MSTL_NODISCARD const_iterator cend() const noexcept {
return ht_.cend(); }
95 MSTL_NODISCARD size_type size() const noexcept {
return ht_.size(); }
96 MSTL_NODISCARD size_type max_size() const noexcept {
return ht_.max_size(); }
97 MSTL_NODISCARD
bool empty() const noexcept {
return ht_.empty(); }
99 MSTL_NODISCARD size_type count(
const key_type& key)
const noexcept(
noexcept(ht_.count(key))) {
100 return ht_.count(key);
102 MSTL_NODISCARD size_type bucket_count() const noexcept {
return ht_.bucket_count(); }
103 MSTL_NODISCARD size_type max_bucket_count() const noexcept {
return ht_.max_bucket_count(); }
104 MSTL_NODISCARD size_type bucket_size(size_type n)
const noexcept {
return ht_.bucket_size(n); }
106 MSTL_NODISCARD allocator_type get_allocator() const noexcept {
return allocator_type(); }
108 MSTL_NODISCARD hasher hash_funct() const noexcept(noexcept(ht_.hash_func())) {
return ht_.hash_func(); }
109 MSTL_NODISCARD key_equal key_eq() const noexcept(noexcept(ht_.key_eql())) {
return ht_.key_eql(); }
111 MSTL_NODISCARD
float load_factor() const noexcept {
return ht_.load_factor(); }
112 MSTL_NODISCARD
float max_load_factor() const noexcept {
return ht_.max_load_factor(); }
113 void max_load_factor(
float new_max)
noexcept { ht_.max_load_factor(new_max); }
115 void rehash(size_type new_size) { ht_.rehash(new_size); }
116 void reserve(size_type max_count) { ht_.reserve(max_count); }
118 template <
typename... Args>
119 iterator emplace(Args&&... args) {
123 iterator insert(
const value_type& obj) {
124 return ht_.insert_equal(obj);
126 iterator insert(value_type&& obj) {
127 return ht_.insert_equal(
_MSTL move(obj));
129 template <
typename Iterator>
130 void insert(Iterator first, Iterator last) { ht_.insert_equal(first, last); }
132 size_type erase(
const key_type& key)
noexcept {
return ht_.erase(key); }
133 iterator erase(iterator it)
noexcept {
return ht_.erase(it); }
134 iterator erase(iterator first, iterator last)
noexcept {
return ht_.erase(first, last); }
135 const_iterator erase(const_iterator it)
noexcept {
return ht_.erase(it); }
136 const_iterator erase(const_iterator first, const_iterator last)
noexcept {
return ht_.erase(first, last); }
137 void clear() noexcept { ht_.clear(); }
139 MSTL_NODISCARD iterator find(
const key_type& key) {
return ht_.find(key); }
140 MSTL_NODISCARD const_iterator find(
const key_type& key)
const {
return ht_.find(key); }
142 MSTL_NODISCARD pair<iterator, iterator> equal_range(
const key_type& key) {
return ht_.equal_range(key); }
143 MSTL_NODISCARD pair<const_iterator, const_iterator> equal_range(
const key_type& key)
const {
144 return ht_.equal_range(key);
147 void swap(unordered_multimap& x)
noexcept(
noexcept(ht_.swap(x.ht_))) { ht_.swap(x.ht_); }
149 MSTL_NODISCARD
bool operator ==(
const unordered_multimap& rhs)
const
150 noexcept(
noexcept(ht_ == rhs.ht_)) {
151 return ht_ == rhs.ht_;
153 MSTL_NODISCARD
bool operator <(
const unordered_multimap& rhs)
const
154 noexcept(
noexcept(ht_ < rhs.ht_)) {
155 return ht_ < rhs.ht_;
158#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
159template <
typename Iterator,
typename HashFcn = hash<iter_map_key_t<Iterator>>,
160 typename Compare = equal_to<iter_map_key_t<Iterator>>,
typename Alloc>
161unordered_multimap(Iterator, Iterator, HashFcn = HashFcn(), Compare = Compare(), Alloc = Alloc())
164template <
typename Key,
typename T,
typename HashFcn = hash<Key>,
typename Compare = equal_to<Key>,
165 typename Alloc = allocator<pair<const Key, T>>>
166unordered_multimap(std::initializer_list<
pair<Key, T>>, HashFcn = HashFcn(), Compare = Compare(), Alloc = Alloc())
167-> unordered_multimap<Key, T, HashFcn, Compare, Alloc>;
169template <
typename Iterator,
typename Alloc>
173template <
typename Iterator,
typename HashFcn,
typename Alloc>
174unordered_multimap(Iterator, Iterator, HashFcn, Alloc) -> unordered_multimap<iter_map_key_t<Iterator>,
177template <
typename Key,
typename T,
typename Alloc>
178unordered_multimap(std::initializer_list<
pair<Key, T>>, Alloc)
179-> unordered_multimap<Key, T, hash<Key>,
equal_to<Key>, Alloc>;
181template <
typename Key,
typename T,
typename HashFcn,
typename Alloc>
182unordered_multimap(std::initializer_list<
pair<Key, T>>, HashFcn, Alloc)
183-> unordered_multimap<Key, T, HashFcn, equal_to<Key>, Alloc>;
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
typename iter_value_t< Iterator >::second_type iter_map_value_t
从映射迭代器中提取值类型
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
void swap()=delete
删除无参数的swap重载