56 template <
typename Key,
typename T,
typename Hash = std::hash<Key>,
57 typename KeyEqual = std::equal_to<
void>>
61 using mapped_type = T;
62 using value_type = std::pair<Key, T>;
63 using size_type = std::size_t;
65 using key_equal = KeyEqual;
66 using reference = value_type &;
67 using const_reference =
const value_type &;
68 using buckets = std::vector<value_type>;
70 template <
typename ContT,
typename IterVal>
struct hm_iterator {
71 using value_type = IterVal;
72 using pointer = value_type *;
73 using reference = value_type &;
74 using iterator_category = std::forward_iterator_tag;
76 bool operator==(
const hm_iterator &other)
const {
77 return other.hm_ == hm_ && other.idx_ == idx_;
79 bool operator!=(
const hm_iterator &other) {
return !(other == *
this); }
81 hm_iterator &operator++() {
87 reference operator*()
const {
return hm_->buckets_[idx_]; }
88 pointer operator->()
const {
return &hm_->buckets_[idx_]; }
91 explicit hm_iterator(ContT *hm) : hm_(hm) { advance_past_empty(); }
92 explicit hm_iterator(ContT *hm, size_type idx) : hm_(hm), idx_(idx) {}
93 template <
typename OtherContT,
typename OtherIterVal>
94 hm_iterator(
const hm_iterator<OtherContT, OtherIterVal> &other)
95 : hm_(other.hm_), idx_(other.idx_) {}
97 void advance_past_empty() {
98 while (idx_ < hm_->buckets_.size() &&
99 key_equal()(hm_->buckets_[idx_].first, hm_->empty_key_)) {
104 ContT *hm_ =
nullptr;
105 typename ContT::size_type idx_ = 0;
109 using iterator = hm_iterator<HashMap, value_type>;
110 using const_iterator = hm_iterator<const HashMap, const value_type>;
113 HashMap(size_type bucket_count, key_type empty_key) : empty_key_(empty_key) {
115 while (pow2 < bucket_count) {
118 buckets_.resize(pow2, std::make_pair(empty_key_, T()));
121 HashMap(
const HashMap &other, size_type bucket_count)
122 : HashMap(bucket_count, other.empty_key_) {
123 for (
auto it = other.begin(); it != other.end(); ++it) {
129 iterator begin() {
return iterator(
this); }
131 const_iterator begin()
const {
return const_iterator(
this); }
133 const_iterator cbegin()
const {
return const_iterator(
this); }
135 iterator end() {
return iterator(
this, buckets_.size()); }
137 const_iterator end()
const {
return const_iterator(
this, buckets_.size()); }
139 const_iterator cend()
const {
return const_iterator(
this, buckets_.size()); }
142 bool empty()
const {
return size() == 0; }
144 size_type size()
const {
return size_; }
146 size_type max_size()
const {
return std::numeric_limits<size_type>::max(); }
150 HashMap other(bucket_count(), empty_key_);
154 std::pair<iterator, bool> insert(
const value_type &value) {
155 return emplace_impl(value.first, value.second);
158 std::pair<iterator, bool> insert(value_type &&value) {
159 return emplace_impl(value.first, std::move(value.second));
162 template <
typename... Args>
163 std::pair<iterator, bool> emplace(Args &&... args) {
164 return emplace_impl(std::forward<Args>(args)...);
167 void erase(iterator it) { erase_impl(it); }
169 size_type erase(
const key_type &key) {
return erase_impl(key); }
171 template <
typename K> size_type erase(
const K &x) {
return erase_impl(x); }
173 void swap(HashMap &other) {
180 mapped_type &at(
const key_type &key) {
return at_impl(key); }
182 template <
typename K> mapped_type &at(
const K &x) {
return at_impl(x); }
184 const mapped_type &at(
const key_type &key)
const {
return at_impl(key); }
186 template <
typename K>
const mapped_type &at(
const K &x)
const {
190 mapped_type &operator[](
const key_type &key) {
191 return emplace_impl(key).first->second;
194 size_type count(
const key_type &key)
const {
return count_impl(key); }
196 template <
typename K> size_type count(
const K &x)
const {
197 return count_impl(x);
200 iterator find(
const key_type &key) {
return find_impl(key); }
202 template <
typename K> iterator find(
const K &x) {
return find_impl(x); }
204 const_iterator find(
const key_type &key)
const {
return find_impl(key); }
206 template <
typename K> const_iterator find(
const K &x)
const {
211 size_type bucket_count() const noexcept {
return buckets_.size(); }
213 size_type max_bucket_count() const noexcept {
214 return std::numeric_limits<size_type>::max();
218 void rehash(size_type count) {
219 count = std::max(count, size() * 2);
220 HashMap other(*
this, count);
224 void reserve(size_type count) {
225 if (count * 2 > buckets_.size()) {
231 hasher hash_function()
const {
return hasher(); }
233 key_equal key_eq()
const {
return key_equal(); }
236 template <
typename K,
typename... Args>
237 std::pair<iterator, bool> emplace_impl(
const K &key, Args &&... args) {
238 assert(!key_equal()(empty_key_, key) &&
"empty key shouldn't be used");
240 for (
size_t idx = key_to_idx(key);; idx = probe_next(idx)) {
241 if (key_equal()(buckets_[idx].first, empty_key_)) {
242 buckets_[idx].second = mapped_type(std::forward<Args>(args)...);
243 buckets_[idx].first = key;
245 return {iterator(
this, idx),
true};
246 }
else if (key_equal()(buckets_[idx].first, key)) {
247 return {iterator(
this, idx),
false};
252 void erase_impl(iterator it) {
253 size_t bucket = it.idx_;
254 for (
size_t idx = probe_next(bucket);; idx = probe_next(idx)) {
255 if (key_equal()(buckets_[idx].first, empty_key_)) {
256 buckets_[bucket].first = empty_key_;
260 size_t ideal = key_to_idx(buckets_[idx].first);
261 if (diff(bucket, ideal) < diff(idx, ideal)) {
263 buckets_[bucket] = buckets_[idx];
269 template <
typename K> size_type erase_impl(
const K &key) {
270 auto it = find_impl(key);
278 template <
typename K> mapped_type &at_impl(
const K &key) {
279 iterator it = find_impl(key);
283 throw std::out_of_range(
"HashMap::at");
286 template <
typename K>
const mapped_type &at_impl(
const K &key)
const {
287 return const_cast<HashMap *
>(
this)->at_impl(key);
290 template <
typename K>
size_t count_impl(
const K &key)
const {
291 return find_impl(key) == end() ? 0 : 1;
294 template <
typename K> iterator find_impl(
const K &key) {
295 assert(!key_equal()(empty_key_, key) &&
"empty key shouldn't be used");
296 for (
size_t idx = key_to_idx(key);; idx = probe_next(idx)) {
297 if (key_equal()(buckets_[idx].first, key)) {
298 return iterator(
this, idx);
300 if (key_equal()(buckets_[idx].first, empty_key_)) {
306 template <
typename K> const_iterator find_impl(
const K &key)
const {
307 return const_cast<HashMap *
>(
this)->find_impl(key);
310 template <
typename K>
size_t key_to_idx(
const K &key)
const {
311 const size_t mask = buckets_.size() - 1;
312 return hasher()(key) & mask;
315 size_t probe_next(
size_t idx)
const {
316 const size_t mask = buckets_.size() - 1;
317 return (idx + 1) & mask;
320 size_t diff(
size_t a,
size_t b)
const {
321 const size_t mask = buckets_.size() - 1;
322 return (buckets_.size() + (a - b)) & mask;
bool operator==(const Array< N, T > &lhs, const Array< N, T > &rhs)
void swap(IntVector< T > &lhs, IntVector< T > &rhs)
bool operator!=(const IntVector< T > &lhs, const IntVector< T > &rhs)