EnTT  3.10.0
dense_set.hpp
1 #ifndef ENTT_CONTAINER_DENSE_SET_HPP
2 #define ENTT_CONTAINER_DENSE_SET_HPP
3 
4 #include <algorithm>
5 #include <cmath>
6 #include <cstddef>
7 #include <functional>
8 #include <iterator>
9 #include <limits>
10 #include <memory>
11 #include <tuple>
12 #include <type_traits>
13 #include <utility>
14 #include <vector>
15 #include "../config/config.h"
16 #include "../core/compressed_pair.hpp"
17 #include "../core/memory.hpp"
18 #include "../core/type_traits.hpp"
19 #include "fwd.hpp"
20 
21 namespace entt {
22 
28 namespace internal {
29 
30 template<typename It>
31 class dense_set_iterator final {
32  template<typename>
33  friend class dense_set_iterator;
34 
35 public:
36  using value_type = typename It::value_type::second_type;
37  using pointer = const value_type *;
38  using reference = const value_type &;
39  using difference_type = std::ptrdiff_t;
40  using iterator_category = std::random_access_iterator_tag;
41 
42  dense_set_iterator() ENTT_NOEXCEPT
43  : it{} {}
44 
45  dense_set_iterator(const It iter) ENTT_NOEXCEPT
46  : it{iter} {}
47 
48  template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
49  dense_set_iterator(const dense_set_iterator<Other> &other) ENTT_NOEXCEPT
50  : it{other.it} {}
51 
52  dense_set_iterator &operator++() ENTT_NOEXCEPT {
53  return ++it, *this;
54  }
55 
56  dense_set_iterator operator++(int) ENTT_NOEXCEPT {
57  dense_set_iterator orig = *this;
58  return ++(*this), orig;
59  }
60 
61  dense_set_iterator &operator--() ENTT_NOEXCEPT {
62  return --it, *this;
63  }
64 
65  dense_set_iterator operator--(int) ENTT_NOEXCEPT {
66  dense_set_iterator orig = *this;
67  return operator--(), orig;
68  }
69 
70  dense_set_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
71  it += value;
72  return *this;
73  }
74 
75  dense_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
76  dense_set_iterator copy = *this;
77  return (copy += value);
78  }
79 
80  dense_set_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
81  return (*this += -value);
82  }
83 
84  dense_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
85  return (*this + -value);
86  }
87 
88  [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
89  return it[value].second;
90  }
91 
92  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
93  return std::addressof(it->second);
94  }
95 
96  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
97  return *operator->();
98  }
99 
100  template<typename ILhs, typename IRhs>
101  friend std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
102 
103  template<typename ILhs, typename IRhs>
104  friend bool operator==(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
105 
106  template<typename ILhs, typename IRhs>
107  friend bool operator<(const dense_set_iterator<ILhs> &, const dense_set_iterator<IRhs> &) ENTT_NOEXCEPT;
108 
109 private:
110  It it;
111 };
112 
113 template<typename ILhs, typename IRhs>
114 [[nodiscard]] std::ptrdiff_t operator-(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
115  return lhs.it - rhs.it;
116 }
117 
118 template<typename ILhs, typename IRhs>
119 [[nodiscard]] bool operator==(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
120  return lhs.it == rhs.it;
121 }
122 
123 template<typename ILhs, typename IRhs>
124 [[nodiscard]] bool operator!=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
125  return !(lhs == rhs);
126 }
127 
128 template<typename ILhs, typename IRhs>
129 [[nodiscard]] bool operator<(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
130  return lhs.it < rhs.it;
131 }
132 
133 template<typename ILhs, typename IRhs>
134 [[nodiscard]] bool operator>(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
135  return rhs < lhs;
136 }
137 
138 template<typename ILhs, typename IRhs>
139 [[nodiscard]] bool operator<=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
140  return !(lhs > rhs);
141 }
142 
143 template<typename ILhs, typename IRhs>
144 [[nodiscard]] bool operator>=(const dense_set_iterator<ILhs> &lhs, const dense_set_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
145  return !(lhs < rhs);
146 }
147 
148 template<typename It>
149 class dense_set_local_iterator final {
150  template<typename>
151  friend class dense_set_local_iterator;
152 
153 public:
154  using value_type = typename It::value_type::second_type;
155  using pointer = const value_type *;
156  using reference = const value_type &;
157  using difference_type = std::ptrdiff_t;
158  using iterator_category = std::forward_iterator_tag;
159 
160  dense_set_local_iterator() ENTT_NOEXCEPT
161  : it{},
162  offset{} {}
163 
164  dense_set_local_iterator(It iter, const std::size_t pos) ENTT_NOEXCEPT
165  : it{iter},
166  offset{pos} {}
167 
168  template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
169  dense_set_local_iterator(const dense_set_local_iterator<Other> &other) ENTT_NOEXCEPT
170  : it{other.it},
171  offset{other.offset} {}
172 
173  dense_set_local_iterator &operator++() ENTT_NOEXCEPT {
174  return offset = it[offset].first, *this;
175  }
176 
177  dense_set_local_iterator operator++(int) ENTT_NOEXCEPT {
178  dense_set_local_iterator orig = *this;
179  return ++(*this), orig;
180  }
181 
182  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
183  return std::addressof(it[offset].second);
184  }
185 
186  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
187  return *operator->();
188  }
189 
190  [[nodiscard]] std::size_t index() const ENTT_NOEXCEPT {
191  return offset;
192  }
193 
194 private:
195  It it;
196  std::size_t offset;
197 };
198 
199 template<typename ILhs, typename IRhs>
200 [[nodiscard]] bool operator==(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
201  return lhs.index() == rhs.index();
202 }
203 
204 template<typename ILhs, typename IRhs>
205 [[nodiscard]] bool operator!=(const dense_set_local_iterator<ILhs> &lhs, const dense_set_local_iterator<IRhs> &rhs) ENTT_NOEXCEPT {
206  return !(lhs == rhs);
207 }
208 
209 } // namespace internal
210 
228 template<typename Type, typename Hash, typename KeyEqual, typename Allocator>
229 class dense_set {
230  static constexpr float default_threshold = 0.875f;
231  static constexpr std::size_t minimum_capacity = 8u;
232 
233  using node_type = std::pair<std::size_t, Type>;
234  using alloc_traits = std::allocator_traits<Allocator>;
235  static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
236  using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>;
237  using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>;
238 
239  template<typename Other>
240  [[nodiscard]] std::size_t value_to_bucket(const Other &value) const ENTT_NOEXCEPT {
241  return fast_mod(sparse.second()(value), bucket_count());
242  }
243 
244  template<typename Other>
245  [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) {
246  for(auto it = begin(bucket), last = end(bucket); it != last; ++it) {
247  if(packed.second()(*it, value)) {
248  return begin() + static_cast<typename iterator::difference_type>(it.index());
249  }
250  }
251 
252  return end();
253  }
254 
255  template<typename Other>
256  [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const {
257  for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) {
258  if(packed.second()(*it, value)) {
259  return cbegin() + static_cast<typename iterator::difference_type>(it.index());
260  }
261  }
262 
263  return cend();
264  }
265 
266  template<typename Other>
267  [[nodiscard]] auto insert_or_do_nothing(Other &&value) {
268  const auto index = value_to_bucket(value);
269 
270  if(auto it = constrained_find(value, index); it != end()) {
271  return std::make_pair(it, false);
272  }
273 
274  packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value));
275  sparse.first()[index] = packed.first().size() - 1u;
276  rehash_if_required();
277 
278  return std::make_pair(--end(), true);
279  }
280 
281  void move_and_pop(const std::size_t pos) {
282  if(const auto last = size() - 1u; pos != last) {
283  packed.first()[pos] = std::move(packed.first().back());
284  size_type *curr = sparse.first().data() + value_to_bucket(packed.first().back().second);
285  for(; *curr != last; curr = &packed.first()[*curr].first) {}
286  *curr = pos;
287  }
288 
289  packed.first().pop_back();
290  }
291 
292  void rehash_if_required() {
293  if(size() > (bucket_count() * max_load_factor())) {
294  rehash(bucket_count() * 2u);
295  }
296  }
297 
298 public:
300  using key_type = Type;
302  using value_type = Type;
304  using size_type = std::size_t;
306  using hasher = Hash;
308  using key_equal = KeyEqual;
310  using allocator_type = Allocator;
312  using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
314  using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
316  using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
318  using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>;
319 
322  : dense_set(minimum_capacity) {}
323 
328  explicit dense_set(const allocator_type &allocator)
329  : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {}
330 
338  : dense_set{bucket_count, hasher{}, key_equal{}, allocator} {}
339 
347  dense_set(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
348  : dense_set{bucket_count, hash, key_equal{}, allocator} {}
349 
358  explicit dense_set(const size_type bucket_count, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{})
359  : sparse{allocator, hash},
360  packed{allocator, equal},
361  threshold{default_threshold} {
363  }
364 
366  dense_set(const dense_set &) = default;
367 
373  dense_set(const dense_set &other, const allocator_type &allocator)
374  : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())},
375  packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())},
376  threshold{other.threshold} {}
377 
379  dense_set(dense_set &&) = default;
380 
386  dense_set(dense_set &&other, const allocator_type &allocator)
387  : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))},
388  packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))},
389  threshold{other.threshold} {}
390 
395  dense_set &operator=(const dense_set &) = default;
396 
401  dense_set &operator=(dense_set &&) = default;
402 
407  [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
408  return sparse.first().get_allocator();
409  }
410 
419  [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
420  return packed.first().begin();
421  }
422 
424  [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
425  return cbegin();
426  }
427 
429  [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
430  return packed.first().begin();
431  }
432 
443  [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
444  return packed.first().end();
445  }
446 
448  [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
449  return cend();
450  }
451 
453  [[nodiscard]] iterator end() ENTT_NOEXCEPT {
454  return packed.first().end();
455  }
456 
461  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
462  return packed.first().empty();
463  }
464 
469  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
470  return packed.first().size();
471  }
472 
474  void clear() ENTT_NOEXCEPT {
475  sparse.first().clear();
476  packed.first().clear();
477  rehash(0u);
478  }
479 
487  std::pair<iterator, bool> insert(const value_type &value) {
488  return insert_or_do_nothing(value);
489  }
490 
492  std::pair<iterator, bool> insert(value_type &&value) {
493  return insert_or_do_nothing(std::move(value));
494  }
495 
502  template<typename It>
503  void insert(It first, It last) {
504  for(; first != last; ++first) {
505  insert(*first);
506  }
507  }
508 
522  template<typename... Args>
523  std::pair<iterator, bool> emplace(Args &&...args) {
524  if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Args>>, value_type>)) {
525  return insert_or_do_nothing(std::forward<Args>(args)...);
526  } else {
527  auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...));
528  const auto index = value_to_bucket(node.second);
529 
530  if(auto it = constrained_find(node.second, index); it != end()) {
531  packed.first().pop_back();
532  return std::make_pair(it, false);
533  }
534 
535  std::swap(node.first, sparse.first()[index]);
536  rehash_if_required();
537 
538  return std::make_pair(--end(), true);
539  }
540  }
541 
548  const auto diff = pos - cbegin();
549  erase(*pos);
550  return begin() + diff;
551  }
552 
560  const auto dist = first - cbegin();
561 
562  for(auto from = last - cbegin(); from != dist; --from) {
563  erase(packed.first()[from - 1u].second);
564  }
565 
566  return (begin() + dist);
567  }
568 
574  size_type erase(const value_type &value) {
575  for(size_type *curr = sparse.first().data() + value_to_bucket(value); *curr != (std::numeric_limits<size_type>::max)(); curr = &packed.first()[*curr].first) {
576  if(packed.second()(packed.first()[*curr].second, value)) {
577  const auto index = *curr;
578  *curr = packed.first()[*curr].first;
579  move_and_pop(index);
580  return 1u;
581  }
582  }
583 
584  return 0u;
585  }
586 
591  void swap(dense_set &other) {
592  using std::swap;
593  swap(sparse, other.sparse);
594  swap(packed, other.packed);
595  swap(threshold, other.threshold);
596  }
597 
604  [[nodiscard]] iterator find(const value_type &value) {
605  return constrained_find(value, value_to_bucket(value));
606  }
607 
609  [[nodiscard]] const_iterator find(const value_type &value) const {
610  return constrained_find(value, value_to_bucket(value));
611  }
612 
620  template<typename Other>
621  [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>>
622  find(const Other &value) {
623  return constrained_find(value, value_to_bucket(value));
624  }
625 
627  template<typename Other>
628  [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>>
629  find(const Other &value) const {
630  return constrained_find(value, value_to_bucket(value));
631  }
632 
638  [[nodiscard]] bool contains(const value_type &value) const {
639  return (find(value) != cend());
640  }
641 
649  template<typename Other>
650  [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>>
651  contains(const Other &value) const {
652  return (find(value) != cend());
653  }
654 
660  [[nodiscard]] const_local_iterator cbegin(const size_type index) const {
661  return {packed.first().begin(), sparse.first()[index]};
662  }
663 
669  [[nodiscard]] const_local_iterator begin(const size_type index) const {
670  return cbegin(index);
671  }
672 
678  [[nodiscard]] local_iterator begin(const size_type index) {
679  return {packed.first().begin(), sparse.first()[index]};
680  }
681 
687  [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const {
688  return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
689  }
690 
696  [[nodiscard]] const_local_iterator end([[maybe_unused]] const size_type index) const {
697  return cend(index);
698  }
699 
705  [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) {
706  return {packed.first().begin(), (std::numeric_limits<size_type>::max)()};
707  }
708 
713  [[nodiscard]] size_type bucket_count() const {
714  return sparse.first().size();
715  }
716 
721  [[nodiscard]] size_type max_bucket_count() const {
722  return sparse.first().max_size();
723  }
724 
730  [[nodiscard]] size_type bucket_size(const size_type index) const {
731  return static_cast<size_type>(std::distance(begin(index), end(index)));
732  }
733 
739  [[nodiscard]] size_type bucket(const value_type &value) const {
740  return value_to_bucket(value);
741  }
742 
747  [[nodiscard]] float load_factor() const {
748  return size() / static_cast<float>(bucket_count());
749  }
750 
755  [[nodiscard]] float max_load_factor() const {
756  return threshold;
757  }
758 
763  void max_load_factor(const float value) {
764  ENTT_ASSERT(value > 0.f, "Invalid load factor");
765  threshold = value;
766  rehash(0u);
767  }
768 
774  void rehash(const size_type count) {
775  auto value = (std::max)(count, minimum_capacity);
776  value = (std::max)(value, static_cast<size_type>(size() / max_load_factor()));
777 
778  if(const auto sz = next_power_of_two(value); sz != bucket_count()) {
779  sparse.first().resize(sz);
780  std::fill(sparse.first().begin(), sparse.first().end(), (std::numeric_limits<size_type>::max)());
781 
782  for(size_type pos{}, last = size(); pos < last; ++pos) {
783  const auto index = value_to_bucket(packed.first()[pos].second);
784  packed.first()[pos].first = std::exchange(sparse.first()[index], pos);
785  }
786  }
787  }
788 
794  void reserve(const size_type count) {
795  packed.first().reserve(count);
796  rehash(static_cast<size_type>(std::ceil(count / max_load_factor())));
797  }
798 
803  [[nodiscard]] hasher hash_function() const {
804  return sparse.second();
805  }
806 
811  [[nodiscard]] key_equal key_eq() const {
812  return packed.second();
813  }
814 
815 private:
818  float threshold;
819 };
820 
821 } // namespace entt
822 
823 #endif
second_type & second()
Returns the second element that a pair stores.
first_type & first()
Returns the first element that a pair stores.
Associative container for unique objects of a given type.
Definition: dense_set.hpp:229
size_type bucket_size(const size_type index) const
Returns the number of elements in a given bucket.
Definition: dense_set.hpp:730
size_type size() const
Returns the number of elements in a container.
Definition: dense_set.hpp:469
dense_set(dense_set &&)=default
Default move constructor.
const_iterator cend() const
Returns an iterator to the end.
Definition: dense_set.hpp:443
bool empty() const
Checks whether a container is empty.
Definition: dense_set.hpp:461
internal::dense_set_local_iterator< typename packed_container_type::const_iterator > const_local_iterator
Constant forward iterator type.
Definition: dense_set.hpp:318
std::pair< iterator, bool > insert(value_type &&value)
Inserts an element into the container, if it does not exist.
Definition: dense_set.hpp:492
key_equal key_eq() const
Returns the function used to compare elements for equality.
Definition: dense_set.hpp:811
KeyEqual key_equal
Type of function to use to compare the elements for equality.
Definition: dense_set.hpp:308
internal::dense_set_iterator< typename packed_container_type::const_iterator > const_iterator
Constant random access iterator type.
Definition: dense_set.hpp:314
iterator erase(const_iterator first, const_iterator last)
Removes the given elements from a container.
Definition: dense_set.hpp:559
std::pair< iterator, bool > emplace(Args &&...args)
Constructs an element in-place, if it does not exist.
Definition: dense_set.hpp:523
Hash hasher
Type of function to use to hash the elements.
Definition: dense_set.hpp:306
std::size_t size_type
Unsigned integer type.
Definition: dense_set.hpp:304
size_type bucket(const value_type &value) const
Returns the bucket for a given element.
Definition: dense_set.hpp:739
iterator find(const value_type &value)
Finds an element with a given value.
Definition: dense_set.hpp:604
constexpr allocator_type get_allocator() const
Returns the associated allocator.
Definition: dense_set.hpp:407
void swap(dense_set &other)
Exchanges the contents with those of a given container.
Definition: dense_set.hpp:591
dense_set(const size_type bucket_count, const allocator_type &allocator)
Constructs an empty container with a given allocator and user supplied minimal number of buckets.
Definition: dense_set.hpp:337
Type key_type
Key type of the container.
Definition: dense_set.hpp:300
const_iterator end() const
Returns an iterator to the end.
Definition: dense_set.hpp:448
void rehash(const size_type count)
Reserves at least the specified number of buckets and regenerates the hash table.
Definition: dense_set.hpp:774
Type value_type
Value type of the container.
Definition: dense_set.hpp:302
dense_set & operator=(const dense_set &)=default
Default copy assignment operator.
internal::dense_set_iterator< typename packed_container_type::iterator > iterator
Random access iterator type.
Definition: dense_set.hpp:312
size_type bucket_count() const
Returns the number of buckets.
Definition: dense_set.hpp:713
const_local_iterator cend([[maybe_unused]] const size_type index) const
Returns an iterator to the end of a given bucket.
Definition: dense_set.hpp:687
local_iterator end([[maybe_unused]] const size_type index)
Returns an iterator to the end of a given bucket.
Definition: dense_set.hpp:705
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.
Definition: dense_set.hpp:622
dense_set(const dense_set &other, const allocator_type &allocator)
Allocator-extended copy constructor.
Definition: dense_set.hpp:373
const_iterator find(const value_type &value) const
Finds an element with a given value.
Definition: dense_set.hpp:609
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition: dense_set.hpp:419
hasher hash_function() const
Returns the function used to hash the elements.
Definition: dense_set.hpp:803
internal::dense_set_local_iterator< typename packed_container_type::iterator > local_iterator
Forward iterator type.
Definition: dense_set.hpp:316
Allocator allocator_type
Allocator type.
Definition: dense_set.hpp:310
const_local_iterator end([[maybe_unused]] const size_type index) const
Returns an iterator to the end of a given bucket.
Definition: dense_set.hpp:696
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.
Definition: dense_set.hpp:651
dense_set(const dense_set &)=default
Default copy constructor.
dense_set(const size_type bucket_count, const hasher &hash, const allocator_type &allocator)
Constructs an empty container with a given allocator, hash function and user supplied minimal number ...
Definition: dense_set.hpp:347
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.
Definition: dense_set.hpp:629
void max_load_factor(const float value)
Sets the desired maximum average number of elements per bucket.
Definition: dense_set.hpp:763
iterator end()
Returns an iterator to the end.
Definition: dense_set.hpp:453
float load_factor() const
Returns the average number of elements per bucket.
Definition: dense_set.hpp:747
size_type erase(const value_type &value)
Removes the element associated with a given value.
Definition: dense_set.hpp:574
dense_set(const size_type bucket_count, 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...
Definition: dense_set.hpp:358
size_type max_bucket_count() const
Returns the maximum number of buckets.
Definition: dense_set.hpp:721
dense_set & operator=(dense_set &&)=default
Default move assignment operator.
const_iterator begin() const
Returns an iterator to the beginning.
Definition: dense_set.hpp:424
dense_set(const allocator_type &allocator)
Constructs an empty container with a given allocator.
Definition: dense_set.hpp:328
dense_set()
Default constructor.
Definition: dense_set.hpp:321
std::pair< iterator, bool > insert(const value_type &value)
Inserts an element into the container, if it does not exist.
Definition: dense_set.hpp:487
void reserve(const size_type count)
Reserves space for at least the specified number of elements and regenerates the hash table.
Definition: dense_set.hpp:794
iterator erase(const_iterator pos)
Removes an element from a given position.
Definition: dense_set.hpp:547
dense_set(dense_set &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition: dense_set.hpp:386
void clear()
Clears the container.
Definition: dense_set.hpp:474
void insert(It first, It last)
Inserts elements into the container, if they do not exist.
Definition: dense_set.hpp:503
float max_load_factor() const
Returns the maximum average number of elements per bucket.
Definition: dense_set.hpp:755
const_local_iterator begin(const size_type index) const
Returns an iterator to the beginning of a given bucket.
Definition: dense_set.hpp:669
local_iterator begin(const size_type index)
Returns an iterator to the beginning of a given bucket.
Definition: dense_set.hpp:678
const_local_iterator cbegin(const size_type index) const
Returns an iterator to the beginning of a given bucket.
Definition: dense_set.hpp:660
bool contains(const value_type &value) const
Checks if the container contains an element with a given value.
Definition: dense_set.hpp:638
iterator begin()
Returns an iterator to the beginning.
Definition: dense_set.hpp:429
EnTT default namespace.
Definition: dense_map.hpp:22
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod)
Fast module utility function (powers of two only).
Definition: memory.hpp:102
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr std::size_t next_power_of_two(const std::size_t value)
Computes the smallest power of two greater than or equal to a value.
Definition: memory.hpp:85
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.
constexpr bool operator<(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
bool operator!=(const basic_any< Len, Align > &lhs, const basic_any< Len, Align > &rhs)
Checks if two wrappers differ in their content.
Definition: any.hpp:402
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.