EnTT  2.7.3
sparse_set.hpp
1 #ifndef ENTT_ENTITY_SPARSE_SET_HPP
2 #define ENTT_ENTITY_SPARSE_SET_HPP
3 
4 
5 #include <algorithm>
6 #include <iterator>
7 #include <numeric>
8 #include <utility>
9 #include <vector>
10 #include <cstddef>
11 #include <cassert>
12 #include <type_traits>
13 #include "../config/config.h"
14 #include "../core/algorithm.hpp"
15 #include "entt_traits.hpp"
16 #include "entity.hpp"
17 
18 
19 namespace entt {
20 
21 
28 template<typename...>
29 class SparseSet;
30 
31 
59 template<typename Entity>
62 
63  class Iterator final {
64  friend class SparseSet<Entity>;
65 
66  using direct_type = const std::vector<Entity>;
67  using index_type = typename traits_type::difference_type;
68 
69  Iterator(direct_type *direct, index_type index) ENTT_NOEXCEPT
70  : direct{direct}, index{index}
71  {}
72 
73  public:
74  using difference_type = index_type;
75  using value_type = const Entity;
76  using pointer = value_type *;
77  using reference = value_type &;
78  using iterator_category = std::random_access_iterator_tag;
79 
80  Iterator() ENTT_NOEXCEPT = default;
81 
82  Iterator(const Iterator &) ENTT_NOEXCEPT = default;
83  Iterator & operator=(const Iterator &) ENTT_NOEXCEPT = default;
84 
85  Iterator & operator++() ENTT_NOEXCEPT {
86  return --index, *this;
87  }
88 
89  Iterator operator++(int) ENTT_NOEXCEPT {
90  Iterator orig = *this;
91  return ++(*this), orig;
92  }
93 
94  Iterator & operator--() ENTT_NOEXCEPT {
95  return ++index, *this;
96  }
97 
98  Iterator operator--(int) ENTT_NOEXCEPT {
99  Iterator orig = *this;
100  return --(*this), orig;
101  }
102 
103  Iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
104  index -= value;
105  return *this;
106  }
107 
108  Iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
109  return Iterator{direct, index-value};
110  }
111 
112  inline Iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
113  return (*this += -value);
114  }
115 
116  inline Iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
117  return (*this + -value);
118  }
119 
120  difference_type operator-(const Iterator &other) const ENTT_NOEXCEPT {
121  return other.index - index;
122  }
123 
124  reference operator[](const difference_type value) const ENTT_NOEXCEPT {
125  const auto pos = size_type(index-value-1);
126  return (*direct)[pos];
127  }
128 
129  bool operator==(const Iterator &other) const ENTT_NOEXCEPT {
130  return other.index == index;
131  }
132 
133  inline bool operator!=(const Iterator &other) const ENTT_NOEXCEPT {
134  return !(*this == other);
135  }
136 
137  bool operator<(const Iterator &other) const ENTT_NOEXCEPT {
138  return index > other.index;
139  }
140 
141  bool operator>(const Iterator &other) const ENTT_NOEXCEPT {
142  return index < other.index;
143  }
144 
145  inline bool operator<=(const Iterator &other) const ENTT_NOEXCEPT {
146  return !(*this > other);
147  }
148 
149  inline bool operator>=(const Iterator &other) const ENTT_NOEXCEPT {
150  return !(*this < other);
151  }
152 
153  pointer operator->() const ENTT_NOEXCEPT {
154  const auto pos = size_type(index-1);
155  return &(*direct)[pos];
156  }
157 
158  inline reference operator*() const ENTT_NOEXCEPT {
159  return *operator->();
160  }
161 
162  private:
163  direct_type *direct;
164  index_type index;
165  };
166 
167 public:
169  using entity_type = Entity;
171  using size_type = std::size_t;
173  using iterator_type = Iterator;
175  using const_iterator_type = Iterator;
176 
178  SparseSet() ENTT_NOEXCEPT = default;
179 
181  virtual ~SparseSet() ENTT_NOEXCEPT = default;
182 
184  SparseSet(const SparseSet &) = delete;
186  SparseSet(SparseSet &&) = default;
187 
189  SparseSet & operator=(const SparseSet &) = delete;
191  SparseSet & operator=(SparseSet &&) = default;
192 
201  void reserve(const size_type cap) {
202  direct.reserve(cap);
203  }
204 
210  size_type capacity() const ENTT_NOEXCEPT {
211  return direct.capacity();
212  }
213 
224  size_type extent() const ENTT_NOEXCEPT {
225  return reverse.size();
226  }
227 
238  size_type size() const ENTT_NOEXCEPT {
239  return direct.size();
240  }
241 
246  bool empty() const ENTT_NOEXCEPT {
247  return direct.empty();
248  }
249 
265  const entity_type * data() const ENTT_NOEXCEPT {
266  return direct.data();
267  }
268 
281  const_iterator_type cbegin() const ENTT_NOEXCEPT {
282  const typename traits_type::difference_type pos = direct.size();
283  return const_iterator_type{&direct, pos};
284  }
285 
298  inline const_iterator_type begin() const ENTT_NOEXCEPT {
299  return cbegin();
300  }
301 
314  inline iterator_type begin() ENTT_NOEXCEPT {
315  return cbegin();
316  }
317 
331  const_iterator_type cend() const ENTT_NOEXCEPT {
332  return const_iterator_type{&direct, {}};
333  }
334 
348  inline const_iterator_type end() const ENTT_NOEXCEPT {
349  return cend();
350  }
351 
365  inline iterator_type end() ENTT_NOEXCEPT {
366  return cend();
367  }
368 
374  inline const entity_type & operator[](const size_type pos) const ENTT_NOEXCEPT {
375  return cbegin()[pos];
376  }
377 
383  bool has(const entity_type entity) const ENTT_NOEXCEPT {
384  const auto pos = size_type(entity & traits_type::entity_mask);
385  // testing against null permits to avoid accessing the direct vector
386  return (pos < reverse.size()) && (reverse[pos] != null);
387  }
388 
406  bool fast(const entity_type entity) const ENTT_NOEXCEPT {
407  const auto pos = size_type(entity & traits_type::entity_mask);
408  assert(pos < reverse.size());
409  // testing against null permits to avoid accessing the direct vector
410  return (reverse[pos] != null);
411  }
412 
425  size_type get(const entity_type entity) const ENTT_NOEXCEPT {
426  assert(has(entity));
427  const auto pos = size_type(entity & traits_type::entity_mask);
428  return size_type(reverse[pos]);
429  }
430 
442  void construct(const entity_type entity) {
443  assert(!has(entity));
444  const auto pos = size_type(entity & traits_type::entity_mask);
445 
446  if(!(pos < reverse.size())) {
447  // null is safe in all cases for our purposes
448  reverse.resize(pos+1, null);
449  }
450 
451  reverse[pos] = entity_type(direct.size());
452  direct.push_back(entity);
453  }
454 
466  virtual void destroy(const entity_type entity) {
467  assert(has(entity));
468  const auto back = direct.back();
469  auto &candidate = reverse[size_type(entity & traits_type::entity_mask)];
470  // swapping isn't required here, we are getting rid of the last element
471  reverse[back & traits_type::entity_mask] = candidate;
472  direct[size_type(candidate)] = back;
473  candidate = null;
474  direct.pop_back();
475  }
476 
492  void swap(const size_type lhs, const size_type rhs) ENTT_NOEXCEPT {
493  assert(lhs < direct.size());
494  assert(rhs < direct.size());
495  auto &src = direct[lhs];
496  auto &dst = direct[rhs];
497  std::swap(reverse[src & traits_type::entity_mask], reverse[dst & traits_type::entity_mask]);
498  std::swap(src, dst);
499  }
500 
520  void respect(const SparseSet<Entity> &other) ENTT_NOEXCEPT {
521  auto from = other.cbegin();
522  auto to = other.cend();
523 
524  size_type pos = direct.size() - 1;
525 
526  while(pos && from != to) {
527  if(has(*from)) {
528  if(*from != direct[pos]) {
529  swap(pos, get(*from));
530  }
531 
532  --pos;
533  }
534 
535  ++from;
536  }
537  }
538 
542  virtual void reset() {
543  reverse.clear();
544  direct.clear();
545  }
546 
547 private:
548  std::vector<entity_type> reverse;
549  std::vector<entity_type> direct;
550 };
551 
552 
575 template<typename Entity, typename Type>
576 class SparseSet<Entity, Type>: public SparseSet<Entity> {
579 
580  template<bool Const>
581  class Iterator final {
582  friend class SparseSet<Entity, Type>;
583 
584  using instance_type = std::conditional_t<Const, const std::vector<Type>, std::vector<Type>>;
585  using index_type = typename traits_type::difference_type;
586 
587  Iterator(instance_type *instances, index_type index) ENTT_NOEXCEPT
588  : instances{instances}, index{index}
589  {}
590 
591  public:
592  using difference_type = index_type;
593  using value_type = std::conditional_t<Const, const Type, Type>;
594  using pointer = value_type *;
595  using reference = value_type &;
596  using iterator_category = std::random_access_iterator_tag;
597 
598  Iterator() ENTT_NOEXCEPT = default;
599 
600  Iterator(const Iterator &) ENTT_NOEXCEPT = default;
601  Iterator & operator=(const Iterator &) ENTT_NOEXCEPT = default;
602 
603  Iterator & operator++() ENTT_NOEXCEPT {
604  return --index, *this;
605  }
606 
607  Iterator operator++(int) ENTT_NOEXCEPT {
608  Iterator orig = *this;
609  return ++(*this), orig;
610  }
611 
612  Iterator & operator--() ENTT_NOEXCEPT {
613  return ++index, *this;
614  }
615 
616  Iterator operator--(int) ENTT_NOEXCEPT {
617  Iterator orig = *this;
618  return --(*this), orig;
619  }
620 
621  Iterator & operator+=(const difference_type value) ENTT_NOEXCEPT {
622  index -= value;
623  return *this;
624  }
625 
626  Iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
627  return Iterator{instances, index-value};
628  }
629 
630  inline Iterator & operator-=(const difference_type value) ENTT_NOEXCEPT {
631  return (*this += -value);
632  }
633 
634  inline Iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
635  return (*this + -value);
636  }
637 
638  difference_type operator-(const Iterator &other) const ENTT_NOEXCEPT {
639  return other.index - index;
640  }
641 
642  reference operator[](const difference_type value) const ENTT_NOEXCEPT {
643  const auto pos = size_type(index-value-1);
644  return (*instances)[pos];
645  }
646 
647  bool operator==(const Iterator &other) const ENTT_NOEXCEPT {
648  return other.index == index;
649  }
650 
651  inline bool operator!=(const Iterator &other) const ENTT_NOEXCEPT {
652  return !(*this == other);
653  }
654 
655  bool operator<(const Iterator &other) const ENTT_NOEXCEPT {
656  return index > other.index;
657  }
658 
659  bool operator>(const Iterator &other) const ENTT_NOEXCEPT {
660  return index < other.index;
661  }
662 
663  inline bool operator<=(const Iterator &other) const ENTT_NOEXCEPT {
664  return !(*this > other);
665  }
666 
667  inline bool operator>=(const Iterator &other) const ENTT_NOEXCEPT {
668  return !(*this < other);
669  }
670 
671  pointer operator->() const ENTT_NOEXCEPT {
672  const auto pos = size_type(index-1);
673  return &(*instances)[pos];
674  }
675 
676  inline reference operator*() const ENTT_NOEXCEPT {
677  return *operator->();
678  }
679 
680  private:
681  instance_type *instances;
682  index_type index;
683  };
684 
685 public:
687  using object_type = Type;
693  using iterator_type = Iterator<false>;
695  using const_iterator_type = Iterator<true>;
696 
698  SparseSet() ENTT_NOEXCEPT = default;
699 
701  SparseSet(const SparseSet &) = delete;
703  SparseSet(SparseSet &&) = default;
704 
706  SparseSet & operator=(const SparseSet &) = delete;
708  SparseSet & operator=(SparseSet &&) = default;
709 
718  void reserve(const size_type cap) {
719  underlying_type::reserve(cap);
720  instances.reserve(cap);
721  }
722 
738  const object_type * raw() const ENTT_NOEXCEPT {
739  return instances.data();
740  }
741 
757  object_type * raw() ENTT_NOEXCEPT {
758  return instances.data();
759  }
760 
773  const_iterator_type cbegin() const ENTT_NOEXCEPT {
774  const typename traits_type::difference_type pos = instances.size();
775  return const_iterator_type{&instances, pos};
776  }
777 
790  inline const_iterator_type begin() const ENTT_NOEXCEPT {
791  return cbegin();
792  }
793 
806  iterator_type begin() ENTT_NOEXCEPT {
807  const typename traits_type::difference_type pos = instances.size();
808  return iterator_type{&instances, pos};
809  }
810 
825  const_iterator_type cend() const ENTT_NOEXCEPT {
826  return const_iterator_type{&instances, {}};
827  }
828 
843  inline const_iterator_type end() const ENTT_NOEXCEPT {
844  return cend();
845  }
846 
861  iterator_type end() ENTT_NOEXCEPT {
862  return iterator_type{&instances, {}};
863  }
864 
870  inline const object_type & operator[](const size_type pos) const ENTT_NOEXCEPT {
871  return cbegin()[pos];
872  }
873 
879  inline object_type & operator[](const size_type pos) ENTT_NOEXCEPT {
880  return const_cast<object_type &>(const_cast<const SparseSet *>(this)->operator[](pos));
881  }
882 
895  const object_type & get(const entity_type entity) const ENTT_NOEXCEPT {
896  return instances[underlying_type::get(entity)];
897  }
898 
911  inline object_type & get(const entity_type entity) ENTT_NOEXCEPT {
912  return const_cast<object_type &>(const_cast<const SparseSet *>(this)->get(entity));
913  }
914 
935  template<typename... Args>
936  std::enable_if_t<std::is_constructible<Type, Args...>::value, object_type &>
937  construct(const entity_type entity, Args &&... args) {
938  underlying_type::construct(entity);
939  instances.emplace_back(std::forward<Args>(args)...);
940  return instances.back();
941  }
942 
963  template<typename... Args>
964  std::enable_if_t<!std::is_constructible<Type, Args...>::value, object_type &>
965  construct(const entity_type entity, Args &&... args) {
966  underlying_type::construct(entity);
967  instances.emplace_back(Type{std::forward<Args>(args)...});
968  return instances.back();
969  }
970 
982  void destroy(const entity_type entity) override {
983  // swapping isn't required here, we are getting rid of the last element
984  // however, we must protect ourselves from self assignments (see #37)
985  auto tmp = std::move(instances.back());
986  instances[underlying_type::get(entity)] = std::move(tmp);
987  instances.pop_back();
988  underlying_type::destroy(entity);
989  }
990 
1032  template<typename Compare, typename Sort = StdSort, typename... Args>
1033  void sort(Compare compare, Sort sort = Sort{}, Args &&... args) {
1034  std::vector<size_type> copy(instances.size());
1035  std::iota(copy.begin(), copy.end(), 0);
1036 
1037  sort(copy.begin(), copy.end(), [this, compare = std::move(compare)](const auto lhs, const auto rhs) {
1038  return compare(const_cast<const object_type &>(instances[rhs]), const_cast<const object_type &>(instances[lhs]));
1039  }, std::forward<Args>(args)...);
1040 
1041  for(size_type pos = 0, last = copy.size(); pos < last; ++pos) {
1042  auto curr = pos;
1043  auto next = copy[curr];
1044 
1045  while(curr != next) {
1046  const auto lhs = copy[curr];
1047  const auto rhs = copy[next];
1048  std::swap(instances[lhs], instances[rhs]);
1049  underlying_type::swap(lhs, rhs);
1050  copy[curr] = curr;
1051  curr = next;
1052  next = copy[curr];
1053  }
1054  }
1055  }
1056 
1080  void respect(const SparseSet<Entity> &other) ENTT_NOEXCEPT {
1081  auto from = other.cbegin();
1082  auto to = other.cend();
1083 
1084  size_type pos = underlying_type::size() - 1;
1085  const auto *local = underlying_type::data();
1086 
1087  while(pos && from != to) {
1088  const auto curr = *from;
1089 
1090  if(underlying_type::has(curr)) {
1091  if(curr != *(local + pos)) {
1092  auto candidate = underlying_type::get(curr);
1093  std::swap(instances[pos], instances[candidate]);
1094  underlying_type::swap(pos, candidate);
1095  }
1096 
1097  --pos;
1098  }
1099 
1100  ++from;
1101  }
1102  }
1103 
1107  void reset() override {
1108  underlying_type::reset();
1109  instances.clear();
1110  }
1111 
1112 private:
1113  std::vector<object_type> instances;
1114 };
1115 
1116 
1117 }
1118 
1119 
1120 #endif // ENTT_ENTITY_SPARSE_SET_HPP
void swap(const size_type lhs, const size_type rhs) ENTT_NOEXCEPT
Swaps the position of two entities in the internal packed array.
Definition: sparse_set.hpp:492
constexpr bool operator!=(const HashedString &lhs, const HashedString &rhs) ENTT_NOEXCEPT
Compares two hashed strings.
const_iterator_type cbegin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
Definition: sparse_set.hpp:773
size_type capacity() const ENTT_NOEXCEPT
Returns the number of elements that a sparse set has currently allocated space for.
Definition: sparse_set.hpp:210
object_type & operator[](const size_type pos) ENTT_NOEXCEPT
Returns a reference to the element at the given position.
Definition: sparse_set.hpp:879
bool empty() const ENTT_NOEXCEPT
Checks whether a sparse set is empty.
Definition: sparse_set.hpp:246
std::enable_if_t<!std::is_constructible< Type, Args... >::value, object_type & > construct(const entity_type entity, Args &&... args)
Assigns an entity to a sparse set and constructs its object.
Definition: sparse_set.hpp:965
bool fast(const entity_type entity) const ENTT_NOEXCEPT
Checks if a sparse set contains an entity (unsafe).
Definition: sparse_set.hpp:406
virtual void reset()
Resets a sparse set.
Definition: sparse_set.hpp:542
EnTT default namespace.
Definition: algorithm.hpp:10
const object_type * raw() const ENTT_NOEXCEPT
Direct access to the array of objects.
Definition: sparse_set.hpp:738
void reset() override
Resets a sparse set.
const_iterator_type cend() const ENTT_NOEXCEPT
Returns an iterator to the end.
Definition: sparse_set.hpp:825
bool has(const entity_type entity) const ENTT_NOEXCEPT
Checks if a sparse set contains an entity.
Definition: sparse_set.hpp:383
const_iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
Definition: sparse_set.hpp:298
void destroy(const entity_type entity) override
Removes an entity from a sparse set and destroies its object.
Definition: sparse_set.hpp:982
const_iterator_type begin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
Definition: sparse_set.hpp:790
Sparse set.
Definition: sparse_set.hpp:29
std::enable_if_t< std::is_constructible< Type, Args... >::value, object_type & > construct(const entity_type entity, Args &&... args)
Assigns an entity to a sparse set and constructs its object.
Definition: sparse_set.hpp:937
constexpr auto null
Null entity.
Definition: entity.hpp:78
std::size_t size_type
Unsigned integer type.
Definition: sparse_set.hpp:171
size_type extent() const ENTT_NOEXCEPT
Returns the extent of a sparse set.
Definition: sparse_set.hpp:224
iterator_type begin() ENTT_NOEXCEPT
Returns an iterator to the beginning.
Definition: sparse_set.hpp:806
void sort(Compare compare, Sort sort=Sort{}, Args &&... args)
Sort components according to the given comparison function.
iterator_type end() ENTT_NOEXCEPT
Returns an iterator to the end.
Definition: sparse_set.hpp:365
iterator_type end() ENTT_NOEXCEPT
Returns an iterator to the end.
Definition: sparse_set.hpp:861
Entity entity_type
Underlying entity identifier.
Definition: sparse_set.hpp:169
Iterator iterator_type
Input iterator type.
Definition: sparse_set.hpp:173
Basic sparse set implementation.
Definition: sparse_set.hpp:60
void respect(const SparseSet< Entity > &other) ENTT_NOEXCEPT
Sort components according to the order of the entities in another sparse set.
Iterator const_iterator_type
Constant input iterator type.
Definition: sparse_set.hpp:175
Type object_type
Type of the objects associated to the entities.
Definition: sparse_set.hpp:687
size_type size() const ENTT_NOEXCEPT
Returns the number of elements in a sparse set.
Definition: sparse_set.hpp:238
const_iterator_type cend() const ENTT_NOEXCEPT
Returns an iterator to the end.
Definition: sparse_set.hpp:331
const_iterator_type end() const ENTT_NOEXCEPT
Returns an iterator to the end.
Definition: sparse_set.hpp:843
Function object to wrap std::sort in a class type.
Definition: algorithm.hpp:21
virtual void destroy(const entity_type entity)
Removes an entity from a sparse set.
Definition: sparse_set.hpp:466
object_type * raw() ENTT_NOEXCEPT
Direct access to the array of objects.
Definition: sparse_set.hpp:757
void respect(const SparseSet< Entity > &other) ENTT_NOEXCEPT
Sort entities according to their order in another sparse set.
Definition: sparse_set.hpp:520
iterator_type begin() ENTT_NOEXCEPT
Returns an iterator to the beginning.
Definition: sparse_set.hpp:314
const entity_type * data() const ENTT_NOEXCEPT
Direct access to the internal packed array.
Definition: sparse_set.hpp:265
const_iterator_type cbegin() const ENTT_NOEXCEPT
Returns an iterator to the beginning.
Definition: sparse_set.hpp:281
const_iterator_type end() const ENTT_NOEXCEPT
Returns an iterator to the end.
Definition: sparse_set.hpp:348
void construct(const entity_type entity)
Assigns an entity to a sparse set.
Definition: sparse_set.hpp:442
const entity_type & operator[](const size_type pos) const ENTT_NOEXCEPT
Returns a reference to the element at the given position.
Definition: sparse_set.hpp:374
const object_type & operator[](const size_type pos) const ENTT_NOEXCEPT
Returns a reference to the element at the given position.
Definition: sparse_set.hpp:870
Entity traits.
Definition: entt_traits.hpp:18