100 using value_type = T;
102 using difference_type = ptrdiff_t;
103 using allocator_type = Allocator;
105 using const_reference = value_type
const &;
107 using const_pointer = value_type
const *;
113 constexpr iterator(node_type *node,
bool used) noexcept : node(node), used(used) {}
115 [[nodiscard]]
constexpr node_type &operator*()
const noexcept
120 [[nodiscard]]
constexpr node_type *operator->()
const noexcept
125 [[nodiscard]]
constexpr friend bool operator==(iterator
const &lhs, std::default_sentinel_t)
noexcept
135 class const_iterator {
137 constexpr const_iterator(node_type *node) noexcept : node(node) {}
139 [[nodiscard]]
constexpr node_type
const &operator*()
const noexcept
144 [[nodiscard]]
constexpr node_type
const *operator->()
const noexcept
149 [[nodiscard]]
constexpr friend bool operator==(
iterator const &lhs, std::default_sentinel_t)
noexcept
158 hash_map(hash_map
const &) =
delete;
159 hash_map(hash_map &&) =
delete;
160 hash_map &operator=(hash_map
const &) =
delete;
161 hash_map &operator=(hash_map &&) =
delete;
163 constexpr hash_map() noexcept requires(allocator_always_equal) : _nodes(
nullptr), _capacity(0), _size(0), allocator()
165 reserve(initial_capacity);
173 std::destroy_n(_nodes, _capacity);
177 [[nodiscard]]
constexpr allocator_type get_allocator() const noexcept
182 hi_no_inline
constexpr void reserve(std::size_t new_capacity)
noexcept
184 if (new_capacity > _capacity) {
187 move_nodes(_nodes, _capacity, new_nodes, new_capacity);
189 if (_nodes !=
nullptr) {
193 _capacity = new_capacity;
197 [[nodiscard]]
constexpr const_iterator
find(key_type
const &key)
const noexcept
202 auto hash = std::hash<key_type>{}(key);
203 hash = hash == 0 ? 1 : hash;
205 auto hash_plus_count = hash;
208 auto node = _nodes + hash_plus_count % _capacity;
209 if (node->hash() == 0 or (node->hash() == hash and node->key() == key)) {
210 return const_iterator{node};
218 [[nodiscard]]
constexpr iterator find_or_create(K &&key)
noexcept
223 auto hash = std::hash<key_type>{}(key);
224 hash = hash == 0 ? 1 : hash;
226 auto hash_plus_count = hash;
229 auto node = _nodes + hash_plus_count % _capacity;
231 if (node->hash() == hash and node->key() == key) {
232 return iterator{node,
true};
234 }
else if (node->hash() == 0) {
243 [[nodiscard]]
constexpr value_type &operator[](K &&key)
noexcept
248 [[nodiscard]]
constexpr std::default_sentinel_t
end() const noexcept
253 [[nodiscard]]
constexpr std::default_sentinel_t cend() const noexcept
259 static constexpr std::size_t initial_capacity = 307;
261 node_type *_nodes =
nullptr;
262 std::size_t _capacity = 0;
263 std::size_t _size = 0;
264 [[no_unique_address]] allocator_type allocator;
267 hi_no_inline
constexpr iterator or_create(node_type &node, std::size_t hash, K &&key)
noexcept
271 return iterator{&node,
false};
279 hi_no_inline
constexpr void move_nodes(node_type *src, std::size_t src_size, node_type *dst, std::size_t dst_size)
noexcept
282 hilet dst_ = std::uninitialized_value_construct_n(dst, dst_size);
285 auto const *
const src_last = src + src_size;
286 for (
auto src_it = src; src_it != src_last; ++src_it) {
288 hilet hash = src_it->hash();
291 auto hash_plus_count = hash;
293 hilet dst_it = dst_ + hash_plus_count % dst_size;
296 if (dst_it->hash() == 0) {
306 std::destroy_n(src, src_size);
309 void grow_by(std::size_t nr_entries)
noexcept
317 hilet max_size = _capacity - (_capacity >> 2);
318 if (_size > max_size) {
321 auto new_capacity = (_capacity + (_capacity >> 1) + nr_entries) | 1;
322 reserve(new_capacity);
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253