EnTT 3.13.0
Loading...
Searching...
No Matches
dense_set.hpp
1#ifndef ENTT_CONTAINER_DENSE_SET_HPP
2#define ENTT_CONTAINER_DENSE_SET_HPP
3
4#include <cmath>
5#include <cstddef>
6#include <functional>
7#include <iterator>
8#include <limits>
9#include <memory>
10#include <tuple>
11#include <type_traits>
12#include <utility>
13#include <vector>
14#include "../config/config.h"
15#include "../core/compressed_pair.hpp"
16#include "../core/memory.hpp"
17#include "../core/type_traits.hpp"
18#include "fwd.hpp"
19
20namespace entt {
21
23namespace internal {
24
25template<typename It>
26class dense_set_iterator final {
27 template<typename>
28 friend class dense_set_iterator;
29
30public:
31 using value_type = typename It::value_type::second_type;
32 using pointer = const value_type *;
33 using reference = const value_type &;
34 using difference_type = std::ptrdiff_t;
35 using iterator_category = std::random_access_iterator_tag;
36
37 constexpr dense_set_iterator() noexcept
38 : it{} {}
39
40 constexpr dense_set_iterator(const It iter) noexcept
41 : it{iter} {}
42
43 template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
44 constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept
45 : it{other.it} {}
46
47 constexpr dense_set_iterator &operator++() noexcept {
48 return ++it, *this;
49 }
50
51 constexpr dense_set_iterator operator++(int) noexcept {
52 dense_set_iterator orig = *this;
53 return ++(*this), orig;
54 }
55
56 constexpr dense_set_iterator &operator--() noexcept {
57 return --it, *this;
58 }
59
60 constexpr dense_set_iterator operator--(int) noexcept {
61 dense_set_iterator orig = *this;
62 return operator--(), orig;
63 }
64
65 constexpr dense_set_iterator &operator+=(const difference_type value) noexcept {
66 it += value;
67 return *this;
68 }
69
70 constexpr dense_set_iterator operator+(const difference_type value) const noexcept {
71 dense_set_iterator copy = *this;
72 return (copy += value);
73 }
74
75 constexpr dense_set_iterator &operator-=(const difference_type value) noexcept {
76 return (*this += -value);
77 }
78
79 constexpr dense_set_iterator operator-(const difference_type value) const noexcept {
80 return (*this + -value);
81 }
82
83 [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
84 return it[value].second;
85 }
86
87 [[nodiscard]] constexpr pointer operator->() const noexcept {
88 return std::addressof(it->second);
89 }
90
91 [[nodiscard]] constexpr reference operator*() const noexcept {
92 return *operator->();
93 }
94
95 template<typename Lhs, typename Rhs>
96 friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
97
98 template<typename Lhs, typename Rhs>
99 friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
100
101 template<typename Lhs, typename Rhs>
102 friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept;
103
104private:
105 It it;
106};
107
108template<typename Lhs, typename Rhs>
109[[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
110 return lhs.it - rhs.it;
111}
112
113template<typename Lhs, typename Rhs>
114[[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
115 return lhs.it == rhs.it;
116}
117
118template<typename Lhs, typename Rhs>
119[[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
120 return !(lhs == rhs);
121}
122
123template<typename Lhs, typename Rhs>
124[[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
125 return lhs.it < rhs.it;
126}
127
128template<typename Lhs, typename Rhs>
129[[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
130 return rhs < lhs;
131}
132
133template<typename Lhs, typename Rhs>
134[[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
135 return !(lhs > rhs);
136}
137
138template<typename Lhs, typename Rhs>
139[[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept {
140 return !(lhs < rhs);
141}
142
143template<typename It>
144class dense_set_local_iterator final {
145 template<typename>
146 friend class dense_set_local_iterator;
147
148public:
149 using value_type = typename It::value_type::second_type;
150 using pointer = const value_type *;
151 using reference = const value_type &;
152 using difference_type = std::ptrdiff_t;
153 using iterator_category = std::forward_iterator_tag;
154
155 constexpr dense_set_local_iterator() noexcept
156 : it{},
157 offset{} {}
158
159 constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept
160 : it{iter},
161 offset{pos} {}
162
163 template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
164 constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept
165 : it{other.it},
166 offset{other.offset} {}
167
168 constexpr dense_set_local_iterator &operator++() noexcept {
169 return offset = it[offset].first, *this;
170 }
171
172 constexpr dense_set_local_iterator operator++(int) noexcept {
173 dense_set_local_iterator orig = *this;
174 return ++(*this), orig;
175 }
176
177 [[nodiscard]] constexpr pointer operator->() const noexcept {
178 return std::addressof(it[offset].second);
179 }
180
181 [[nodiscard]] constexpr reference operator*() const noexcept {
182 return *operator->();
183 }
184
185 [[nodiscard]] constexpr std::size_t index() const noexcept {
186 return offset;
187 }
188
189private:
190 It it;
191 std::size_t offset;
192};
193
194template<typename Lhs, typename Rhs>
195[[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
196 return lhs.index() == rhs.index();
197}
198
199template<typename Lhs, typename Rhs>
200[[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept {
201 return !(lhs == rhs);
202}
203
204} // namespace internal
219template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
221 static constexpr float default_threshold = 0.875f;
222 static constexpr std::size_t minimum_capacity = 8u;
223
224 using node_type = std::pair<std::size_t, Type>;
225 using alloc_traits = std::allocator_traits<Allocator>;
226 static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
227 using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
228 using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
229
230 template<typename Other>
231 [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept {
232 return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count());
233 }
234
235 template<typename Other>
236 [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) {
237 for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
238 if(packed.second()(*it, value)) {
239 return begin() + static_cast<typename iterator::difference_type>(it.index());
240 }
241 }
242
243 return end();
244 }
245
246 template<typename Other>
247 [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const {
248 for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
249 if(packed.second()(*it, value)) {
250 return cbegin() + static_cast<typename iterator::difference_type>(it.index());
251 }
252 }
253
254 return cend();
255 }
256
257 template<typename Other>
258 [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
259 const auto index = value_to_bucket(value);
260
261 if(auto it = constrained_find(value, index); it != end()) {
262 return std::make_pair(it, false);
263 }
264
265 packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
266 sparse.first()[index] = packed.first().size() - 1u;
267 rehash_if_required();
268
269 return std::make_pair(--end(), true);
270 }
271
272 void move_and_pop(const std::size_t pos) {
273 if(const auto last = size() - 1u; pos != last) {
274 size_type *curr = sparse.first().data() + value_to_bucket(packed.first().back().second);
275 packed.first()[pos] = std::move(packed.first().back());
276 for(; *curr != last; curr = &packed.first()[*curr].first) {}
277 *curr = pos;
278 }
279
280 packed.first().pop_back();
281 }
282
283 void rehash_if_required() {
284 if(size() > (bucket_count() * max_load_factor())) {
285 rehash(bucket_count() * 2u);
286 }
287 }
288
289public:
291 using key_type = Type;
293 using value_type = Type;
295 using size_type = std::size_t;
297 using hasher = Hash;
299 using key_equal = KeyEqual;
301 using allocator_type = Allocator;
303 using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
305 using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
307 using reverse_iterator = std::reverse_iterator<iterator>;
309 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
311 using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
313 using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
314
317 : dense_set{minimum_capacity} {}
318
323 explicit dense_set(const allocator_type &allocator)
324 : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
325
332 dense_set(const size_type cnt, const allocator_type &allocator)
333 : dense_set{cnt, hasher{}, key_equal{}, allocator} {}
334
342 dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
343 : dense_set{cnt, hash, key_equal{}, allocator} {}
344
353 explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
354 : sparse{allocator, hash},
355 packed{allocator, equal},
356 threshold{default_threshold} {
357 rehash(cnt);
358 }
359
361 dense_set(const dense_set &) = default;
362
368 dense_set(const dense_set &other, const allocator_type &allocator)
369 : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
370 packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
371 threshold{other.threshold} {}
372
374 dense_set(dense_set &&) noexcept(std::is_nothrow_move_constructible_v<compressed_pair<sparse_container_type, hasher>> &&std::is_nothrow_move_constructible_v<compressed_pair<packed_container_type, key_equal>>) = default;
375
381 dense_set(dense_set &&other, const allocator_type &allocator)
382 : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
383 packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
384 threshold{other.threshold} {}
385
390 dense_set &operator=(const dense_set &) = default;
391
396 dense_set &operator=(dense_set &&) noexcept(std::is_nothrow_move_assignable_v<compressed_pair<sparse_container_type, hasher>> &&std::is_nothrow_move_assignable_v<compressed_pair<packed_container_type, key_equal>>) = default;
397
402 [[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
403 return sparse.first().get_allocator();
404 }
405
413 [[nodiscard]] const_iterator cbegin() const noexcept {
414 return packed.first().begin();
415 }
416
418 [[nodiscard]] const_iterator begin() const noexcept {
419 return cbegin();
420 }
421
423 [[nodiscard]] iterator begin() noexcept {
424 return packed.first().begin();
425 }
426
432 [[nodiscard]] const_iterator cend() const noexcept {
433 return packed.first().end();
434 }
435
437 [[nodiscard]] const_iterator end() const noexcept {
438 return cend();
439 }
440
442 [[nodiscard]] iterator end() noexcept {
443 return packed.first().end();
444 }
445
453 [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
454 return std::make_reverse_iterator(cend());
455 }
456
458 [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
459 return crbegin();
460 }
461
463 [[nodiscard]] reverse_iterator rbegin() noexcept {
464 return std::make_reverse_iterator(end());
465 }
466
472 [[nodiscard]] const_reverse_iterator crend() const noexcept {
473 return std::make_reverse_iterator(cbegin());
474 }
475
477 [[nodiscard]] const_reverse_iterator rend() const noexcept {
478 return crend();
479 }
480
482 [[nodiscard]] reverse_iterator rend() noexcept {
483 return std::make_reverse_iterator(begin());
484 }
485
490 [[nodiscard]] bool empty() const noexcept {
491 return packed.first().empty();
492 }
493
498 [[nodiscard]] size_type size() const noexcept {
499 return packed.first().size();
500 }
501
506 [[nodiscard]] size_type max_size() const noexcept {
507 return packed.first().max_size();
508 }
509
511 void clear() noexcept {
512 sparse.first().clear();
513 packed.first().clear();
514 rehash(0u);
515 }
516
524 std::pair<iterator, bool> insert(const value_type &value) {
525 return insert_or_do_nothing(value);
526 }
527
529 std::pair<iterator, bool> insert(value_type &&value) {
530 return insert_or_do_nothing(std::move(value));
531 }
532
539 template<typename It>
540 void insert(It first, It last) {
541 for(; first != last; ++first) {
542 insert(*first);
543 }
544 }
545
559 template<typename... Args>
560 std::pair<iterator, bool> emplace(Args &&...args) {
561 if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) {
562 return insert_or_do_nothing(std::forward<Args>(args)...);
563 } else {
564 auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
565 const auto index = value_to_bucket(node.second);
566
567 if(auto it = constrained_find(node.second, index); it != end()) {
568 packed.first().pop_back();
569 return std::make_pair(it, false);
570 }
571
572 std::swap(node.first, sparse.first()[index]);
573 rehash_if_required();
574
575 return std::make_pair(--end(), true);
576 }
577 }
578
585 const auto diff = pos - cbegin();
586 erase(*pos);
587 return begin() + diff;
588 }
589
597 const auto dist = first - cbegin();
598
599 for(auto from = last - cbegin(); from != dist; --from) {
600 erase(packed.first()[from - 1u].second);
601 }
602
603 return (begin() + dist);
604 }
605
611 size_type erase(const value_type &value) {
612 for(size_type *curr = sparse.first().data() + value_to_bucket(value); *curr != (std::numeric_limits<size_type>::max)(); curr = &packed.first()[*curr].first) {
613 if(packed.second()(packed.first()[*curr].second, value)) {
614 const auto index = *curr;
615 *curr = packed.first()[*curr].first;
616 move_and_pop(index);
617 return 1u;
618 }
619 }
620
621 return 0u;
622 }
623
628 void swap(dense_set &other) {
629 using std::swap;
630 swap(sparse, other.sparse);
631 swap(packed, other.packed);
632 swap(threshold, other.threshold);
633 }
634
640 [[nodiscard]] size_type count(const value_type &key) const {
641 return find(key) != end();
642 }
643
650 template<typename Other>
651 [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>>
652 count(const Other &key) const {
653 return find(key) != end();
654 }
655
662 [[nodiscard]] iterator find(const value_type &value) {
663 return constrained_find(value, value_to_bucket(value));
664 }
665
667 [[nodiscard]] const_iterator find(const value_type &value) const {
668 return constrained_find(value, value_to_bucket(value));
669 }
670
678 template<typename Other>
679 [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
680 find(const Other &value) {
681 return constrained_find(value, value_to_bucket(value));
682 }
683
685 template<typename Other>
686 [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
687 find(const Other &value) const {
688 return constrained_find(value, value_to_bucket(value));
689 }
690
697 [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
698 const auto it = find(value);
699 return {it, it + !(it == end())};
700 }
701
703 [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
704 const auto it = find(value);
705 return {it, it + !(it == cend())};
706 }
707
716 template<typename Other>
717 [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
718 equal_range(const Other &value) {
719 const auto it = find(value);
720 return {it, it + !(it == end())};
721 }
722
724 template<typename Other>
725 [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
726 equal_range(const Other &value) const {
727 const auto it = find(value);
728 return {it, it + !(it == cend())};
729 }
730
736 [[nodiscard]] bool contains(const value_type &value) const {
737 return (find(value) != cend());
738 }
739
747 template<typename Other>
748 [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
749 contains(const Other &value) const {
750 return (find(value) != cend());
751 }
752
758 [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
759 return {packed.first().begin(), sparse.first()[index]};
760 }
761
767 [[nodiscard]] const_local_iterator begin(const size_type index) const {
768 return cbegin(index);
769 }
770
776 [[nodiscard]] local_iterator begin(const size_type index) {
777 return {packed.first().begin(), sparse.first()[index]};
778 }
779
785 [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
786 return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
787 }
788
794 [[nodiscard]] const_local_iterator end(const size_type index) const {
795 return cend(index);
796 }
797
803 [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
804 return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
805 }
806
811 [[nodiscard]] size_type bucket_count() const {
812 return sparse.first().size();
813 }
814
819 [[nodiscard]] size_type max_bucket_count() const {
820 return sparse.first().max_size();
821 }
822
828 [[nodiscard]] size_type bucket_size(const size_type index) const {
829 return static_cast<size_type>(std::distance(begin(index), end(index)));
830 }
831
837 [[nodiscard]] size_type bucket(const value_type &value) const {
838 return value_to_bucket(value);
839 }
840
845 [[nodiscard]] float load_factor() const {
846 return size() / static_cast<float>(bucket_count());
847 }
848
853 [[nodiscard]] float max_load_factor() const {
854 return threshold;
855 }
856
861 void max_load_factor(const float value) {
862 ENTT_ASSERT(value > 0.f, "Invalid load factor");
863 threshold = value;
864 rehash(0u);
865 }
866
872 void rehash(const size_type cnt) {
873 auto value = cnt > minimum_capacity ? cnt : minimum_capacity;
874 const auto cap = static_cast<size_type>(size() / max_load_factor());
875 value = value > cap ? value : cap;
876
877 if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
878 sparse.first().resize(sz);
879
880 for(auto &&elem: sparse.first()) {
881 elem = (std::numeric_limits<size_type>::max)();
882 }
883
884 for(size_type pos{}, last = size(); pos < last; ++pos) {
885 const auto index = value_to_bucket(packed.first()[pos].second);
886 packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
887 }
888 }
889 }
890
896 void reserve(const size_type cnt) {
897 packed.first().reserve(cnt);
898 rehash(static_cast<size_type>(std::ceil(cnt / max_load_factor())));
899 }
900
905 [[nodiscard]] hasher hash_function() const {
906 return sparse.second();
907 }
908
913 [[nodiscard]] key_equal key_eq() const {
914 return packed.second();
915 }
916
917private:
920 float threshold;
921};
922
923} // namespace entt
924
925#endif
A compressed pair.
constexpr second_type & second() noexcept
Returns the second element that a pair stores.
constexpr first_type & first() noexcept
Returns the first element that a pair stores.
Associative container for unique objects of a given type.
size_type bucket_size(const size_type index) const
Returns the number of elements in a given bucket.
void clear() noexcept
Clears the container.
internal::dense_set_local_iterator< typename packed_container_type::const_iterator > const_local_iterator
Constant forward iterator type.
const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator to the beginning.
dense_set & operator=(dense_set &&) noexcept(std::is_nothrow_move_assignable_v< compressed_pair< sparse_container_type, hasher > > &&std::is_nothrow_move_assignable_v< compressed_pair< packed_container_type, key_equal > >)=default
Default move assignment operator.
const_iterator begin() const noexcept
Returns an iterator to the beginning.
key_equal key_eq() const
Returns the function used to compare elements for equality.
KeyEqual key_equal
Type of function to use to compare the elements for equality.
internal::dense_set_iterator< typename packed_container_type::const_iterator > const_iterator
Constant random access iterator type.
const_iterator cend() const noexcept
Returns an iterator to the end.
iterator erase(const_iterator first, const_iterator last)
Removes the given elements from a container.
std::enable_if_t< is_transparent_v< hasher > &&is_transparent_v< key_equal >, std::conditional_t< false, Other, bool > > contains(const Other &value) const
Checks if the container contains an element that compares equivalent to a given value.
Hash hasher
Type of function to use to hash the elements.
std::size_t size_type
Unsigned integer type.
size_type bucket(const value_type &value) const
Returns the bucket for a given element.
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
iterator find(const value_type &value)
Finds an element with a given value.
void swap(dense_set &other)
Exchanges the contents with those of a given container.
Type key_type
Key type of the container.
Type value_type
Value type of the container.
internal::dense_set_iterator< typename packed_container_type::iterator > iterator
Random access iterator type.
std::pair< iterator, bool > emplace(Args &&...args)
Constructs an element in-place, if it does not exist.
size_type bucket_count() const
Returns the number of buckets.
size_type max_size() const noexcept
Returns the maximum possible number of elements.
size_type size() const noexcept
Returns the number of elements in a container.
dense_set(dense_set &&) noexcept(std::is_nothrow_move_constructible_v< compressed_pair< sparse_container_type, hasher > > &&std::is_nothrow_move_constructible_v< compressed_pair< packed_container_type, key_equal > >)=default
Default move constructor.
std::pair< iterator, iterator > equal_range(const value_type &value)
Returns a range containing all elements with a given value.
std::reverse_iterator< const_iterator > const_reverse_iterator
Constant reverse iterator type.
std::enable_if_t< is_transparent_v< hasher > &&is_transparent_v< key_equal >, std::conditional_t< false, Other, std::pair< iterator, iterator > > > equal_range(const Other &value)
Returns a range containing all elements that compare equivalent to a given value.
local_iterator end(const size_type index)
Returns an iterator to the end of a given bucket.
dense_set(const dense_set &other, const allocator_type &allocator)
Allocator-extended copy constructor.
bool empty() const noexcept
Checks whether a container is empty.
dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator)
Constructs an empty container with a given allocator, hash function and user supplied minimal number ...
const_iterator find(const value_type &value) const
Finds an element with a given value.
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
dense_set(const size_type cnt, const allocator_type &allocator)
Constructs an empty container with a given allocator and user supplied minimal number of buckets.
hasher hash_function() const
Returns the function used to hash the elements.
std::pair< iterator, bool > insert(const value_type &value)
Inserts an element into the container, if it does not exist.
internal::dense_set_local_iterator< typename packed_container_type::iterator > local_iterator
Forward iterator type.
void reserve(const size_type cnt)
Reserves space for at least the specified number of elements and regenerates the hash table.
const_local_iterator cend(const size_type index) const
Returns an iterator to the end of a given bucket.
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
Allocator allocator_type
Allocator type.
size_type count(const value_type &key) const
Returns the number of elements matching a value (either 1 or 0).
iterator end() noexcept
Returns an iterator to the end.
std::enable_if_t< is_transparent_v< hasher > &&is_transparent_v< key_equal >, std::conditional_t< false, Other, const_iterator > > find(const Other &value) const
Finds an element with a given value.
dense_set(const dense_set &)=default
Default copy constructor.
const_local_iterator end(const size_type index) const
Returns an iterator to the end of a given bucket.
void max_load_factor(const float value)
Sets the desired maximum average number of elements per bucket.
float load_factor() const
Returns the average number of elements per bucket.
size_type erase(const value_type &value)
Removes the element associated with a given value.
std::pair< iterator, bool > insert(value_type &&value)
Inserts an element into the container, if it does not exist.
size_type max_bucket_count() const
Returns the maximum number of buckets.
dense_set(const allocator_type &allocator)
Constructs an empty container with a given allocator.
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
dense_set()
Default constructor.
const_iterator end() const noexcept
Returns an iterator to the end.
dense_set & operator=(const dense_set &)=default
Default copy assignment operator.
dense_set(const size_type cnt, const hasher &hash=hasher{}, const key_equal &equal=key_equal{}, const allocator_type &allocator=allocator_type{})
Constructs an empty container with a given allocator, hash function, compare function and user suppli...
iterator erase(const_iterator pos)
Removes an element from a given position.
std::enable_if_t< is_transparent_v< hasher > &&is_transparent_v< key_equal >, std::conditional_t< false, Other, iterator > > find(const Other &value)
Finds an element that compares equivalent to a given value.
void rehash(const size_type cnt)
Reserves at least the specified number of buckets and regenerates the hash table.
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
std::enable_if_t< is_transparent_v< hasher > &&is_transparent_v< key_equal >, std::conditional_t< false, Other, size_type > > count(const Other &key) const
Returns the number of elements matching a key (either 1 or 0).
constexpr allocator_type get_allocator() const noexcept
Returns the associated allocator.
void insert(It first, It last)
Inserts elements into the container, if they do not exist.
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
float max_load_factor() const
Returns the maximum average number of elements per bucket.
std::enable_if_t< is_transparent_v< hasher > &&is_transparent_v< key_equal >, std::conditional_t< false, Other, std::pair< const_iterator, const_iterator > > > equal_range(const Other &value) const
Returns a range containing all elements with a given value.
std::pair< const_iterator, const_iterator > equal_range(const value_type &value) const
Returns a range containing all elements with a given value.
const_local_iterator begin(const size_type index) const
Returns an iterator to the beginning of a given bucket.
local_iterator begin(const size_type index)
Returns an iterator to the beginning of a given bucket.
const_local_iterator cbegin(const size_type index) const
Returns an iterator to the beginning of a given bucket.
bool contains(const value_type &value) const
Checks if the container contains an element with a given value.
iterator begin() noexcept
Returns an iterator to the beginning.
EnTT default namespace.
Definition dense_map.hpp:21
constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) noexcept
Fast module utility function (powers of two only).
Definition memory.hpp:47
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator<(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.
constexpr std::size_t next_power_of_two(const std::size_t value) noexcept
Computes the smallest power of two greater than or equal to a value (waiting for C++20 and std::bit_c...
Definition memory.hpp:30
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.