EnTT  3.9.0
sparse_set.hpp
1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP
2 #define ENTT_ENTITY_SPARSE_SET_HPP
3 
4 #include <cstddef>
5 #include <iterator>
6 #include <memory>
7 #include <type_traits>
8 #include <utility>
9 #include <vector>
10 #include "../config/config.h"
11 #include "../core/algorithm.hpp"
12 #include "../core/any.hpp"
13 #include "../core/memory.hpp"
14 #include "../core/type_info.hpp"
15 #include "entity.hpp"
16 #include "fwd.hpp"
17 
18 namespace entt {
19 
25 namespace internal {
26 
27 template<typename Container>
28 struct sparse_set_iterator final {
29  using value_type = typename Container::value_type;
30  using pointer = typename Container::const_pointer;
31  using reference = typename Container::const_reference;
32  using difference_type = typename Container::difference_type;
33  using iterator_category = std::random_access_iterator_tag;
34 
35  sparse_set_iterator() ENTT_NOEXCEPT = default;
36 
37  sparse_set_iterator(const Container &ref, const difference_type idx) ENTT_NOEXCEPT
38  : packed{std::addressof(ref)},
39  offset{idx} {}
40 
41  sparse_set_iterator &operator++() ENTT_NOEXCEPT {
42  return --offset, *this;
43  }
44 
45  sparse_set_iterator operator++(int) ENTT_NOEXCEPT {
46  sparse_set_iterator orig = *this;
47  return ++(*this), orig;
48  }
49 
50  sparse_set_iterator &operator--() ENTT_NOEXCEPT {
51  return ++offset, *this;
52  }
53 
54  sparse_set_iterator operator--(int) ENTT_NOEXCEPT {
55  sparse_set_iterator orig = *this;
56  return operator--(), orig;
57  }
58 
59  sparse_set_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
60  offset -= value;
61  return *this;
62  }
63 
64  sparse_set_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
65  sparse_set_iterator copy = *this;
66  return (copy += value);
67  }
68 
69  sparse_set_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
70  return (*this += -value);
71  }
72 
73  sparse_set_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
74  return (*this + -value);
75  }
76 
77  [[nodiscard]] reference operator[](const difference_type value) const {
78  const auto pos = offset - value - 1;
79  return packed->data()[pos];
80  }
81 
82  [[nodiscard]] pointer operator->() const {
83  const auto pos = offset - 1;
84  return packed->data() + pos;
85  }
86 
87  [[nodiscard]] reference operator*() const {
88  return *operator->();
89  }
90 
91  [[nodiscard]] difference_type index() const ENTT_NOEXCEPT {
92  return offset;
93  }
94 
95 private:
96  const Container *packed;
97  difference_type offset;
98 };
99 
100 template<typename Type, typename Other>
101 [[nodiscard]] auto operator-(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
102  return rhs.index() - lhs.index();
103 }
104 
105 template<typename Type, typename Other>
106 [[nodiscard]] bool operator==(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
107  return lhs.index() == rhs.index();
108 }
109 
110 template<typename Type, typename Other>
111 [[nodiscard]] bool operator!=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
112  return !(lhs == rhs);
113 }
114 
115 template<typename Type, typename Other>
116 [[nodiscard]] bool operator<(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
117  return lhs.index() > rhs.index();
118 }
119 
120 template<typename Type, typename Other>
121 [[nodiscard]] bool operator>(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
122  return lhs.index() < rhs.index();
123 }
124 
125 template<typename Type, typename Other>
126 [[nodiscard]] bool operator<=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
127  return !(lhs > rhs);
128 }
129 
130 template<typename Type, typename Other>
131 [[nodiscard]] bool operator>=(const sparse_set_iterator<Type> &lhs, const sparse_set_iterator<Other> &rhs) ENTT_NOEXCEPT {
132  return !(lhs < rhs);
133 }
134 
135 } // namespace internal
136 
143 enum class deletion_policy : std::uint8_t {
145  swap_and_pop = 0u,
147  in_place = 1u
148 };
149 
173 template<typename Entity, typename Allocator>
175  using allocator_traits = std::allocator_traits<Allocator>;
176  using alloc = typename allocator_traits::template rebind_alloc<Entity>;
177  using alloc_traits = typename std::allocator_traits<alloc>;
178 
180  using sparse_container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
181  using packed_container_type = std::vector<Entity, alloc>;
182 
183  [[nodiscard]] auto sparse_ptr(const Entity entt) const {
184  const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
185  const auto page = pos / entity_traits::page_size;
186  return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, entity_traits::page_size)) : nullptr;
187  }
188 
189  [[nodiscard]] auto &sparse_ref(const Entity entt) const {
190  ENTT_ASSERT(sparse_ptr(entt), "Invalid element");
191  const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
192  return sparse[pos / entity_traits::page_size][fast_mod(pos, entity_traits::page_size)];
193  }
194 
195  void release_sparse_pages() {
196  auto page_allocator{packed.get_allocator()};
197 
198  for(auto &&page: sparse) {
199  if(page != nullptr) {
200  std::destroy(page, page + entity_traits::page_size);
201  alloc_traits::deallocate(page_allocator, page, entity_traits::page_size);
202  page = nullptr;
203  }
204  }
205  }
206 
207 protected:
212  virtual const void *get_at(const std::size_t) const ENTT_NOEXCEPT {
213  return nullptr;
214  }
215 
217  virtual void swap_at(const std::size_t, const std::size_t) {}
218 
220  virtual void move_and_pop(const std::size_t, const std::size_t) {}
221 
226  virtual void swap_and_pop(const Entity entt) {
227  auto &ref = sparse_ref(entt);
228  const auto pos = static_cast<size_type>(entity_traits::to_entity(ref));
229  ENTT_ASSERT(packed[pos] == entt, "Invalid identifier");
230 
231  packed[pos] = packed.back();
232  auto &elem = sparse_ref(packed.back());
234  // lazy self-assignment guard
235  ref = null;
236  // unnecessary but it helps to detect nasty bugs
237  ENTT_ASSERT((packed.back() = tombstone, true), "");
238  packed.pop_back();
239  }
240 
245  virtual void in_place_pop(const Entity entt) {
246  auto &ref = sparse_ref(entt);
247  const auto pos = static_cast<size_type>(entity_traits::to_entity(ref));
248  ENTT_ASSERT(packed[pos] == entt, "Invalid identifier");
249 
250  packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
251  // lazy self-assignment guard
252  ref = null;
253  }
254 
259  virtual void try_emplace(const Entity entt, const void * = nullptr) {
260  const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
261  const auto page = pos / entity_traits::page_size;
262 
263  if(!(page < sparse.size())) {
264  sparse.resize(page + 1u, nullptr);
265  }
266 
267  if(!sparse[page]) {
268  auto page_allocator{packed.get_allocator()};
269  sparse[page] = alloc_traits::allocate(page_allocator, entity_traits::page_size);
270  std::uninitialized_fill(sparse[page], sparse[page] + entity_traits::page_size, null);
271  }
272 
273  auto &elem = sparse[page][fast_mod(pos, entity_traits::page_size)];
274  ENTT_ASSERT(entity_traits::to_version(elem) == entity_traits::to_version(tombstone), "Slot not available");
275 
276  if(free_list == null) {
277  elem = entity_traits::combine(static_cast<typename entity_traits::entity_type>(packed.size()), entity_traits::to_integral(entt));
278  packed.push_back(entt);
279  } else {
281  free_list = std::exchange(packed[static_cast<size_type>(entity_traits::to_entity(free_list))], entt);
282  }
283  }
284 
285 public:
287  using allocator_type = Allocator;
289  using entity_type = Entity;
293  using size_type = typename packed_container_type::size_type;
295  using pointer = typename packed_container_type::const_pointer;
297  using iterator = internal::sparse_set_iterator<packed_container_type>;
301  using reverse_iterator = std::reverse_iterator<iterator>;
304 
307  : basic_sparse_set{type_id<void>()} {}
308 
313  explicit basic_sparse_set(const allocator_type &allocator)
314  : basic_sparse_set{type_id<void>(), deletion_policy::swap_and_pop, allocator} {}
315 
321  explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {})
322  : basic_sparse_set{type_id<void>(), pol, allocator} {}
323 
330  explicit basic_sparse_set(const type_info &value, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {})
331  : sparse{allocator},
332  packed{allocator},
333  info{&value},
334  free_list{tombstone},
335  mode{pol} {}
336 
341  basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
342  : sparse{std::move(other.sparse)},
343  packed{std::move(other.packed)},
344  info{other.info},
345  free_list{std::exchange(other.free_list, tombstone)},
346  mode{other.mode} {}
347 
353  basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator) ENTT_NOEXCEPT
354  : sparse{std::move(other.sparse), allocator},
355  packed{std::move(other.packed), allocator},
356  info{other.info},
357  free_list{std::exchange(other.free_list, tombstone)},
358  mode{other.mode} {
359  ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
360  }
361 
363  virtual ~basic_sparse_set() {
364  release_sparse_pages();
365  }
366 
372  basic_sparse_set &operator=(basic_sparse_set &&other) ENTT_NOEXCEPT {
373  ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
374 
375  release_sparse_pages();
376  sparse = std::move(other.sparse);
377  packed = std::move(other.packed);
378  info = other.info;
379  free_list = std::exchange(other.free_list, tombstone);
380  mode = other.mode;
381  return *this;
382  }
383 
388  void swap(basic_sparse_set &other) {
389  using std::swap;
390  swap(sparse, other.sparse);
391  swap(packed, other.packed);
392  swap(info, other.info);
393  swap(free_list, other.free_list);
394  swap(mode, other.mode);
395  }
396 
401  [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
402  return packed.get_allocator();
403  }
404 
409  [[nodiscard]] deletion_policy policy() const ENTT_NOEXCEPT {
410  return mode;
411  }
412 
417  [[nodiscard]] size_type slot() const ENTT_NOEXCEPT {
418  return free_list == null ? packed.size() : static_cast<size_type>(entity_traits::to_entity(free_list));
419  }
420 
429  virtual void reserve(const size_type cap) {
430  packed.reserve(cap);
431  }
432 
438  [[nodiscard]] virtual size_type capacity() const ENTT_NOEXCEPT {
439  return packed.capacity();
440  }
441 
443  virtual void shrink_to_fit() {
444  packed.shrink_to_fit();
445  }
446 
457  [[nodiscard]] size_type extent() const ENTT_NOEXCEPT {
458  return sparse.size() * entity_traits::page_size;
459  }
460 
471  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
472  return packed.size();
473  }
474 
479  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
480  return packed.empty();
481  }
482 
487  [[nodiscard]] pointer data() const ENTT_NOEXCEPT {
488  return packed.data();
489  }
490 
500  [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
501  const auto pos = static_cast<typename iterator::difference_type>(packed.size());
502  return iterator{packed, pos};
503  }
504 
506  [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
507  return begin();
508  }
509 
520  [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
521  return iterator{packed, {}};
522  }
523 
525  [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
526  return end();
527  }
528 
539  [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
540  return std::make_reverse_iterator(end());
541  }
542 
544  [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT {
545  return rbegin();
546  }
547 
558  [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
559  return std::make_reverse_iterator(begin());
560  }
561 
563  [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT {
564  return rend();
565  }
566 
573  [[nodiscard]] iterator find(const entity_type entt) const ENTT_NOEXCEPT {
574  return contains(entt) ? --(end() - index(entt)) : end();
575  }
576 
582  [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
583  const auto elem = sparse_ptr(entt);
584  constexpr auto cap = entity_traits::to_entity(null);
585  // testing versions permits to avoid accessing the packed array
586  return elem && (((~cap & entity_traits::to_integral(entt)) ^ entity_traits::to_integral(*elem)) < cap);
587  }
588 
595  [[nodiscard]] version_type current(const entity_type entt) const {
596  const auto elem = sparse_ptr(entt);
597  constexpr auto fallback = entity_traits::to_version(tombstone);
598  return elem ? entity_traits::to_version(*elem) : fallback;
599  }
600 
611  [[nodiscard]] size_type index(const entity_type entt) const ENTT_NOEXCEPT {
612  ENTT_ASSERT(contains(entt), "Set does not contain entity");
613  return static_cast<size_type>(entity_traits::to_entity(sparse_ref(entt)));
614  }
615 
621  [[nodiscard]] entity_type at(const size_type pos) const ENTT_NOEXCEPT {
622  return pos < packed.size() ? packed[pos] : null;
623  }
624 
630  [[nodiscard]] entity_type operator[](const size_type pos) const ENTT_NOEXCEPT {
631  ENTT_ASSERT(pos < packed.size(), "Position is out of bounds");
632  return packed[pos];
633  }
634 
645  const void *get(const entity_type entt) const ENTT_NOEXCEPT {
646  ENTT_ASSERT(contains(entt), "Set does not contain entity");
647  return get_at(index(entt));
648  }
649 
651  void *get(const entity_type entt) ENTT_NOEXCEPT {
652  return const_cast<void *>(std::as_const(*this).get(entt));
653  }
654 
665  void emplace(const entity_type entt, const void *value = nullptr) {
666  try_emplace(entt, value);
667  ENTT_ASSERT(contains(entt), "Emplace did not take place");
668  }
669 
681  template<typename It>
682  void insert(It first, It last) {
683  for(; first != last && free_list != null; ++first) {
684  emplace(*first);
685  }
686 
687  reserve(packed.size() + std::distance(first, last));
688 
689  for(; first != last; ++first) {
690  emplace(*first);
691  }
692  }
693 
703  void erase(const entity_type entt) {
704  ENTT_ASSERT(contains(entt), "Set does not contain entity");
706  ENTT_ASSERT(!contains(entt), "Destruction did not take place");
707  }
708 
718  template<typename It>
719  void erase(It first, It last) {
720  for(; first != last; ++first) {
721  erase(*first);
722  }
723  }
724 
730  bool remove(const entity_type entt) {
731  return contains(entt) && (erase(entt), true);
732  }
733 
741  template<typename It>
742  size_type remove(It first, It last) {
743  size_type found{};
744 
745  for(; first != last; ++first) {
746  found += remove(*first);
747  }
748 
749  return found;
750  }
751 
753  void compact() {
754  size_type next = packed.size();
755  for(; next && packed[next - 1u] == tombstone; --next) {}
756 
757  for(auto *it = &free_list; *it != null && next; it = std::addressof(packed[entity_traits::to_entity(*it)])) {
758  if(const size_type pos = entity_traits::to_entity(*it); pos < next) {
759  --next;
760  move_and_pop(next, pos);
761  std::swap(packed[next], packed[pos]);
762  const auto entity = static_cast<typename entity_traits::entity_type>(pos);
763  sparse_ref(packed[pos]) = entity_traits::combine(entity, entity_traits::to_integral(packed[pos]));
765  for(; next && packed[next - 1u] == tombstone; --next) {}
766  }
767  }
768 
769  free_list = tombstone;
770  packed.resize(next);
771  }
772 
786  void swap_elements(const entity_type lhs, const entity_type rhs) {
787  ENTT_ASSERT(contains(lhs) && contains(rhs), "Set does not contain entities");
788 
789  auto &entt = sparse_ref(lhs);
790  auto &other = sparse_ref(rhs);
791 
792  const auto from = entity_traits::to_entity(entt);
793  const auto to = entity_traits::to_entity(other);
794 
795  // basic no-leak guarantee (with invalid state) if swapping throws
796  swap_at(static_cast<size_type>(from), static_cast<size_type>(to));
798  other = entity_traits::combine(from, entity_traits::to_integral(packed[to]));
799  std::swap(packed[from], packed[to]);
800  }
801 
832  template<typename Compare, typename Sort = std_sort, typename... Args>
833  void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&...args) {
834  ENTT_ASSERT(!(length > packed.size()), "Length exceeds the number of elements");
835  ENTT_ASSERT(free_list == null, "Partial sorting with tombstones is not supported");
836 
837  algo(packed.rend() - length, packed.rend(), std::move(compare), std::forward<Args>(args)...);
838 
839  for(size_type pos{}; pos < length; ++pos) {
840  auto curr = pos;
841  auto next = index(packed[curr]);
842 
843  while(curr != next) {
844  const auto idx = index(packed[next]);
845  const auto entt = packed[curr];
846 
847  swap_at(next, idx);
848  const auto entity = static_cast<typename entity_traits::entity_type>(curr);
849  sparse_ref(entt) = entity_traits::combine(entity, entity_traits::to_integral(packed[curr]));
850  curr = std::exchange(next, idx);
851  }
852  }
853  }
854 
867  template<typename Compare, typename Sort = std_sort, typename... Args>
868  void sort(Compare compare, Sort algo = Sort{}, Args &&...args) {
869  compact();
870  sort_n(packed.size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
871  }
872 
888  void respect(const basic_sparse_set &other) {
889  compact();
890 
891  const auto to = other.end();
892  auto from = other.begin();
893 
894  for(size_type pos = packed.size() - 1; pos && from != to; ++from) {
895  if(contains(*from)) {
896  if(*from != packed[pos]) {
897  // basic no-leak guarantee (with invalid state) if swapping throws
898  swap_elements(packed[pos], *from);
899  }
900 
901  --pos;
902  }
903  }
904  }
905 
907  void clear() {
908  for(auto &&entity: *this) {
909  // honor the modality and filter all tombstones
910  remove(entity);
911  }
912  }
913 
918  const type_info &type() const ENTT_NOEXCEPT {
919  return *info;
920  }
921 
923  virtual void bind(any) ENTT_NOEXCEPT {}
924 
925 private:
926  sparse_container_type sparse;
927  packed_container_type packed;
928  const type_info *info;
929  entity_type free_list;
930  deletion_policy mode;
931 };
932 
933 } // namespace entt
934 
935 #endif
Basic sparse set implementation.
Definition: sparse_set.hpp:174
deletion_policy policy() const
Returns the deletion policy of a sparse set.
Definition: sparse_set.hpp:409
void erase(const entity_type entt)
Erases an entity from a sparse set.
Definition: sparse_set.hpp:703
void swap(basic_sparse_set &other)
Exchanges the contents with those of a given sparse set.
Definition: sparse_set.hpp:388
const_reverse_iterator crbegin() const
Returns a reverse iterator to the beginning.
Definition: sparse_set.hpp:544
void insert(It first, It last)
Assigns one or more entities to a sparse set.
Definition: sparse_set.hpp:682
size_type index(const entity_type entt) const
Returns the position of an entity in a sparse set.
Definition: sparse_set.hpp:611
basic_sparse_set(const allocator_type &allocator)
Constructs an empty container with a given allocator.
Definition: sparse_set.hpp:313
reverse_iterator rend() const
Returns a reverse iterator to the end.
Definition: sparse_set.hpp:558
void erase(It first, It last)
Erases entities from a set.
Definition: sparse_set.hpp:719
const_reverse_iterator crend() const
Returns a reverse iterator to the end.
Definition: sparse_set.hpp:563
void swap_elements(const entity_type lhs, const entity_type rhs)
Swaps two entities in a sparse set.
Definition: sparse_set.hpp:786
iterator end() const
Returns an iterator to the end.
Definition: sparse_set.hpp:520
bool empty() const
Checks whether a sparse set is empty.
Definition: sparse_set.hpp:479
iterator const_iterator
Constant random access iterator type.
Definition: sparse_set.hpp:299
size_type slot() const
Returns the next slot available for insertion.
Definition: sparse_set.hpp:417
entity_type operator[](const size_type pos) const
Returns the entity at specified location, without bounds checking.
Definition: sparse_set.hpp:630
virtual void bind(any)
Forwards variables to mixins, if any.
Definition: sparse_set.hpp:923
virtual void swap_and_pop(const Entity entt)
Erase an entity from a sparse set.
Definition: sparse_set.hpp:226
basic_sparse_set(const type_info &value, deletion_policy pol=deletion_policy::swap_and_pop, const allocator_type &allocator={})
Constructs an empty container with the given policy and allocator.
Definition: sparse_set.hpp:330
void sort_n(const size_type length, Compare compare, Sort algo=Sort{}, Args &&...args)
Sort the first count elements according to the given comparison function.
Definition: sparse_set.hpp:833
virtual const void * get_at(const std::size_t) const
Returns the element assigned to an entity.
Definition: sparse_set.hpp:212
reverse_iterator const_reverse_iterator
Constant reverse iterator type.
Definition: sparse_set.hpp:303
version_type current(const entity_type entt) const
Returns the contained version for an identifier.
Definition: sparse_set.hpp:595
void emplace(const entity_type entt, const void *value=nullptr)
Assigns an entity to a sparse set.
Definition: sparse_set.hpp:665
virtual void reserve(const size_type cap)
Increases the capacity of a sparse set.
Definition: sparse_set.hpp:429
const void * get(const entity_type entt) const
Returns the element assigned to an entity, if any.
Definition: sparse_set.hpp:645
void clear()
Clears a sparse set.
Definition: sparse_set.hpp:907
typename packed_container_type::size_type size_type
Unsigned integer type.
Definition: sparse_set.hpp:293
size_type size() const
Returns the number of elements in a sparse set.
Definition: sparse_set.hpp:471
virtual void swap_at(const std::size_t, const std::size_t)
Swaps two entities in a sparse set.
Definition: sparse_set.hpp:217
internal::sparse_set_iterator< packed_container_type > iterator
Random access iterator type.
Definition: sparse_set.hpp:297
virtual void shrink_to_fit()
Requests the removal of unused capacity.
Definition: sparse_set.hpp:443
iterator find(const entity_type entt) const
Finds an entity.
Definition: sparse_set.hpp:573
typename packed_container_type::const_pointer pointer
Pointer type to contained entities.
Definition: sparse_set.hpp:295
basic_sparse_set(deletion_policy pol, const allocator_type &allocator={})
Constructs an empty container with the given policy and allocator.
Definition: sparse_set.hpp:321
typename entity_traits::version_type version_type
Underlying version type.
Definition: sparse_set.hpp:291
Entity entity_type
Underlying entity identifier.
Definition: sparse_set.hpp:289
basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition: sparse_set.hpp:353
size_type extent() const
Returns the extent of a sparse set.
Definition: sparse_set.hpp:457
entity_type at(const size_type pos) const
Returns the entity at specified location, with bounds checking.
Definition: sparse_set.hpp:621
const_iterator begin() const
Returns an iterator to the beginning.
Definition: sparse_set.hpp:500
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition: sparse_set.hpp:506
size_type remove(It first, It last)
Removes entities from a sparse set if they exist.
Definition: sparse_set.hpp:742
basic_sparse_set(basic_sparse_set &&other)
Move constructor.
Definition: sparse_set.hpp:341
virtual void move_and_pop(const std::size_t, const std::size_t)
Moves an entity in a sparse set.
Definition: sparse_set.hpp:220
virtual void in_place_pop(const Entity entt)
Erase an entity from a sparse set.
Definition: sparse_set.hpp:245
const type_info & type() const
Returned value type, if any.
Definition: sparse_set.hpp:918
virtual size_type capacity() const
Returns the number of elements that a sparse set has currently allocated space for.
Definition: sparse_set.hpp:438
virtual ~basic_sparse_set()
Default destructor.
Definition: sparse_set.hpp:363
bool contains(const entity_type entt) const
Checks if a sparse set contains an entity.
Definition: sparse_set.hpp:582
virtual void try_emplace(const Entity entt, const void *=nullptr)
Assigns an entity to a sparse set.
Definition: sparse_set.hpp:259
void respect(const basic_sparse_set &other)
Sort entities according to their order in another sparse set.
Definition: sparse_set.hpp:888
pointer data() const
Direct access to the internal packed array.
Definition: sparse_set.hpp:487
constexpr allocator_type get_allocator() const
Returns the associated allocator.
Definition: sparse_set.hpp:401
void sort(Compare compare, Sort algo=Sort{}, Args &&...args)
Sort all elements according to the given comparison function.
Definition: sparse_set.hpp:868
const_reverse_iterator rbegin() const
Returns a reverse iterator to the beginning.
Definition: sparse_set.hpp:539
const_iterator cend() const
Returns an iterator to the end.
Definition: sparse_set.hpp:525
bool remove(const entity_type entt)
Removes an entity from a sparse set if it exists.
Definition: sparse_set.hpp:730
void * get(const entity_type entt)
Returns the element assigned to an entity, if any.
Definition: sparse_set.hpp:651
void compact()
Removes all tombstones from the packed array of a sparse set.
Definition: sparse_set.hpp:753
Allocator allocator_type
Allocator type.
Definition: sparse_set.hpp:287
basic_sparse_set()
Default constructor.
Definition: sparse_set.hpp:306
basic_sparse_set & operator=(basic_sparse_set &&other)
Move assignment operator.
Definition: sparse_set.hpp:372
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
Definition: sparse_set.hpp:301
Entity traits.
Definition: entity.hpp:62
static constexpr auto page_size
Page size, default is ENTT_SPARSE_PAGE.
Definition: entity.hpp:75
typename base_type::entity_type entity_type
Underlying entity type.
Definition: entity.hpp:69
static constexpr entity_type reserved
Reserved identifier.
Definition: entity.hpp:73
static constexpr entity_type to_integral(const value_type value)
Converts an entity to its underlying type.
Definition: entity.hpp:82
static constexpr entity_type to_entity(const value_type value)
Returns the entity part once converted to the underlying type.
Definition: entity.hpp:91
static constexpr value_type combine(const entity_type lhs, const entity_type rhs)
Combines two identifiers in a single one.
Definition: entity.hpp:128
typename base_type::version_type version_type
Underlying version type.
Definition: entity.hpp:71
static constexpr version_type to_version(const value_type value)
Returns the version part once converted to the underlying type.
Definition: entity.hpp:100
Implementation specific information about a type.
Definition: type_info.hpp:141
EnTT default namespace.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
entity
Default entity identifier.
Definition: fwd.hpp:47
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:101
const type_info & type_id()
Returns the type info object associated to a given type.
Definition: type_info.hpp:256
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
Definition: entity.hpp:335
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.
deletion_policy
Sparse set deletion policy.
Definition: sparse_set.hpp:143
@ swap_and_pop
Swap-and-pop deletion policy.
@ in_place
In-place deletion policy.
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:406
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
Function object to wrap std::sort in a class type.
Definition: algorithm.hpp:21