mCRL2
Loading...
Searching...
No Matches
unordered_map.h
Go to the documentation of this file.
1// Author(s): Maurice Laveaux
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9#ifndef MCRL2_UTILITIES_UNORDERED_MAP_H
10#define MCRL2_UTILITIES_UNORDERED_MAP_H
11
12#include <utility>
13#include <functional>
15
16
17namespace mcrl2::utilities
18{
19
21template<typename Key,
22 typename T,
23 typename Hash,
24 typename KeyEqual,
25 typename Allocator,
26 bool ThreadSafe,
27 bool Resize>
29{
30public:
31 using key_type = Key;
32 using mapped_type = T;
33 using value_type = std::pair<const Key, T>;
35 using size_type = std::size_t;
36 using difference_type = std::ptrdiff_t;
37
38 using hasher = Hash;
39 using key_equal = KeyEqual;
40 using allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<value_type>;
41
44 using pointer = typename std::allocator_traits<Allocator>::pointer;
45 using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
46
47private:
50
51 // Hashes only the keys of each pair.
52 struct PairHash
53 {
54 using is_transparent = void;
55
56 PairHash() = default;
57
58 explicit PairHash(const hasher& hash)
59 : hash(hash)
60 {}
61
63
64 std::size_t operator()(const value_type& pair) const
65 {
66 return hash(pair.first);
67 }
68
69 template<typename U, typename ...V, typename = std::enable_if_t<!std::is_same_v<U, std::pair<Key, T>>>>
70 std::size_t operator()(const U& key, const V&... /* args */) const
71 {
72 return hash(key);
73 }
74 };
75
76 // Compares only the keys of each pair.
78 {
79 using is_transparent = void;
80
81 PairEquals() = default;
82
83 explicit PairEquals(const key_equal& equals)
84 : equals(equals)
85 {}
86
88
89 bool operator()(const value_type& first, const value_type& second) const
90 {
91 return equals(first.first, second.first);
92 }
93
94 template <typename U, typename...V, typename = std::enable_if_t<!std::is_same_v<U, std::pair<Key, T>>>>
95 bool operator()(const value_type& first, const U& key, const V&... /* args */) const
96 {
97 return equals(first.first, key);
98 }
99 };
100
103
105
106public:
107 using iterator = typename Set::template unordered_set_iterator<bucket_type, false>;
109 using local_iterator = typename bucket_type::iterator;
111 typedef typename std::pair<unordered_map::iterator, bool> insert_return_type;
112
115 {}
116
118 unordered_map(std::size_t initial_size,
119 const hasher& hash = hasher(),
120 const key_equal& equals = key_equal())
121 : m_set(initial_size, PairHash(hash), PairEquals(equals))
122 {}
123
125 const allocator_type& get_allocator() const noexcept { return m_set.get_allocator(); }
127
128 iterator begin() { return m_set.begin(); }
129 iterator end() { return m_set.end(); }
130
131 const_iterator begin() const { return m_set.begin(); }
132 const_iterator end() const { return m_set.end(); }
133
134 const_iterator cbegin() const { return m_set.begin(); }
135 const_iterator cend() const { return m_set.end(); }
136
138 bool empty() const noexcept { return m_set.empty(); }
139
141 size_type size() const { return m_set.size(); }
142 size_type max_size() const noexcept { return m_set.max_size(); }
143
145 void clear() { m_set.clear(); }
146
148 std::pair<iterator, bool> insert(const value_type& pair) { auto[x, y] = m_set.emplace(pair); return std::make_pair(iterator(x), y); }
149
150 std::pair<iterator, bool> insert(const_iterator hint, const value_type& pair) { return insert(hint, pair); }
151
152 template<typename ...Args>
153 std::pair<iterator, bool> emplace(Args&&... args) { auto[x, y] = m_set.emplace(std::forward<Args>(args)...); return std::make_pair(iterator(x), y); }
154
155 template<typename ...Args>
156 iterator emplace_hint(const_iterator /*hint*/, Args&&... args) { return emplace(std::forward<Args>(args)...); }
157
158 template<typename ...Args>
159 std::pair<iterator, bool> try_emplace(const key_type& key, Args&&... args);
160
161 template< class... Args >
162 iterator try_emplace(const_iterator /*hint*/, const Key& k, Args&&... args) { return try_emplace(k, std::forward<Args>(args)...); }
163
164 template< class... Args >
165 iterator try_emplace(const_iterator /*hint*/, Key&& k, Args&&... args) { return try_emplace(std::forward<Key>(k), std::forward<Args>(args)...); }
166
167 template <typename M>
168 std::pair<iterator, bool> insert_or_assign(Key&& k, M&& obj)
169 {
170 auto it = find(k);
171 if (it != end())
172 {
173 *it = obj;
174 return std::make_pair(it, true);
175 }
176 else
177 {
178 return emplace(std::forward<Key>(obj), std::forward<M>(obj));
179 }
180 }
181
182 template <typename M>
183 std::pair<iterator, bool> insert_or_assign(const Key& k, M&& obj) { return insert_or_emplace(k, std::forward<M>(obj)); }
184
185 template <typename M>
186 std::pair<iterator, bool> insert_or_assign(const_iterator /* hint */, const Key& k, M&& obj) { return insert_or_emplace(k, std::forward<M>(obj)); }
187
188 template <typename M>
189 std::pair<iterator, bool> insert_or_assign(const_iterator /* hint */, Key&& k, M&& obj) { return insert_or_emplace(k, std::forward<M>(obj)); }
190
192 void erase(const key_type& key) { const_iterator it = m_set.find(key); m_set.erase(it); }
194
196 const T& at(const key_type& key) const;
197
201
203 size_type count(const key_type& key) const { return m_set.count(key); }
204
206 template<typename ...Args>
207 iterator find(const Args&... args) { return m_set.find(args...); }
208
209 template<typename ...Args>
210 const_iterator find(const Args&... args) const { return m_set.find(args...); }
211
215
218
221
223 size_type bucket_count() const noexcept { return m_set.bucket_count(); }
224 size_type max_bucket_count() const noexcept { return m_set.max_bucket_count(); }
225
226 size_type bucket_size(size_type n) const noexcept { return m_set.bucket_size(n); }
227 size_type bucket(const key_type& key) const noexcept { return m_set.bucket(key); }
228
229 float load_factor() const { return static_cast<float>(size()) / bucket_count(); }
230 float max_load_factor() const { return m_set.max_load_factor(); }
231 void max_load_factor(float factor) { m_set.max_load_factor(factor); }
232
234 void rehash(size_type number_of_buckets)
235 {
236 m_set.rehash(number_of_buckets);
237 }
238
240 void reserve(size_type count) { rehash(std::ceil(static_cast<float>(count) / max_load_factor())); }
241
243 key_equal key_eq() const { return m_set.key_eq(); }
244
248};
249
251template<typename Key,
252 typename T,
253 typename Hash = std::hash<Key>,
254 typename Equals = std::equal_to<Key>,
255 typename Allocator = mcrl2::utilities::block_allocator<Key>,
256 bool ThreadSafe = false,
257 bool Resize = true>
259
260} // namespace mcrl2::utilities
261
263
264#endif // MCRL2_UTILITIES_UNORDERED_MAP_H
The block allocator provides the allocator interface for the memory pool class. As such is can be use...
A class for a map of keys to values in T based using the simple hash table set implementation.
void clear()
Clears the content.
unordered_map(std::size_t initial_size, const hasher &hash=hasher(), const key_equal &equals=key_equal())
Constructs an unordered_map that can store initial_size number of elements before resizing.
size_type bucket_size(size_type n) const noexcept
std::pair< iterator, bool > insert_or_assign(const Key &k, M &&obj)
local_iterator begin(size_type n)
size_type max_size() const noexcept
std::pair< iterator, bool > try_emplace(const key_type &key, Args &&... args)
iterator find(const Args &... args)
typename Set::bucket_type bucket_type
iterator try_emplace(const_iterator, const Key &k, Args &&... args)
const_iterator cend() const
std::pair< iterator, bool > insert(const_iterator hint, const value_type &pair)
const allocator_type & get_allocator() const noexcept
const_local_iterator cend(size_type n) const
size_type bucket(const key_type &key) const noexcept
typename std::allocator_traits< Allocator >::pointer pointer
std::pair< iterator, bool > insert(const value_type &pair)
Inserts elements.
const_iterator begin() const
const_iterator find(const Args &... args) const
typename Set::const_local_iterator const_local_iterator
void rehash(size_type number_of_buckets)
Resize the number buckets to at least number_of_buckets.
typename std::allocator_traits< Allocator >::const_pointer const_pointer
typename Set::template unordered_set_iterator< bucket_type, false > iterator
const T & at(const key_type &key) const
Provides access to the value associated with the given key.
const value_type & const_reference
std::pair< unordered_map::iterator, bool > insert_return_type
typename std::allocator_traits< Allocator >::template rebind_alloc< value_type > allocator_type
std::pair< iterator, bool > insert_or_assign(const_iterator, const Key &k, M &&obj)
allocator_type & get_allocator() noexcept
bool empty() const noexcept
mapped_type & operator[](const key_type &key)
Provides access to the value associated with the given key, constructs a default value whenever the k...
void erase(const key_type &key)
Erases elements.
iterator try_emplace(const_iterator, Key &&k, Args &&... args)
typename Set::const_iterator const_iterator
const_iterator end() const
const_local_iterator end(size_type n) const
std::pair< iterator, bool > insert_or_assign(const_iterator, Key &&k, M &&obj)
Set m_set
The underlying set storing <key, value> pairs.
const_local_iterator cbegin(size_type n) const
std::pair< const Key, T > value_type
size_type count(const key_type &key) const
const_iterator cbegin() const
typename bucket_type::iterator local_iterator
iterator erase(const_iterator it)
void reserve(size_type count)
Resizes the set to the given number of elements.
iterator emplace_hint(const_iterator, Args &&... args)
const_local_iterator begin(size_type n) const
void max_load_factor(float factor)
size_type bucket_count() const noexcept
size_type capacity()
Number of elements that can be stored before rehash.
local_iterator end(size_type n)
size_type max_bucket_count() const noexcept
std::pair< iterator, bool > insert_or_assign(Key &&k, M &&obj)
std::pair< iterator, bool > emplace(Args &&... args)
static constexpr bool allow_transparent
True iff the hash and equals functions allow transparent lookup,.
void erase(const Args &... args)
Erases the given key_type(args...) from the unordered set.
size_type count(const Args &... args) const
Counts the number of occurrences of the given key (1 when it exists and 0 otherwise).
size_type bucket_count() const noexcept
bool empty() const noexcept
size_type max_bucket_count() const noexcept
std::pair< iterator, bool > emplace(Args &&... args)
Inserts an element Key(args...) into the set if it did not already exist.
detail::bucket_list< value_type, allocator_type > bucket_type
Combine the bucket list and a lock that locks modifications to the bucket list.
size_type size() const noexcept
void clear()
Removes all elements from the set.
size_type max_size() const noexcept
size_type bucket(const key_type &key) const noexcept
size_type capacity() const noexcept
const_iterator find(const Args &... args) const
Searches whether an object key_type(args...) occurs in the set.
void rehash(size_type number_of_buckets)
Resize the number buckets to at least number_of_buckets.
size_type bucket_size(size_type n) const noexcept
const allocator_type & get_allocator() const noexcept
bool operator()(const value_type &first, const value_type &second) const
bool operator()(const value_type &first, const U &key, const V &...) const
std::size_t operator()(const U &key, const V &...) const
std::size_t operator()(const value_type &pair) const
#define hash(l, r, m)
Definition tree_set.cpp:23