sparse_set.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #ifndef ENTT_COMPONENT_POOL_HPP
  2. #define ENTT_COMPONENT_POOL_HPP
  3. #include <utility>
  4. #include <vector>
  5. #include <cstddef>
  6. #include <cassert>
  7. namespace entt {
  8. template<typename...>
  9. class SparseSet;
  10. template<typename Index>
  11. class SparseSet<Index> {
  12. struct SparseSetIterator;
  13. public:
  14. using index_type = Index;
  15. using pos_type = index_type;
  16. using size_type = std::size_t;
  17. using iterator_type = SparseSetIterator;
  18. private:
  19. struct SparseSetIterator {
  20. using value_type = index_type;
  21. SparseSetIterator(const std::vector<index_type> *direct, size_type pos)
  22. : direct{direct}, pos{pos}
  23. {}
  24. SparseSetIterator & operator++() noexcept {
  25. return --pos, *this;
  26. }
  27. SparseSetIterator operator++(int) noexcept {
  28. SparseSetIterator orig = *this;
  29. return ++(*this), orig;
  30. }
  31. bool operator==(const SparseSetIterator &other) const noexcept {
  32. return other.pos == pos && other.direct == direct;
  33. }
  34. bool operator!=(const SparseSetIterator &other) const noexcept {
  35. return !(*this == other);
  36. }
  37. value_type operator*() const noexcept {
  38. return (*direct)[pos-1];
  39. }
  40. private:
  41. const std::vector<index_type> *direct;
  42. size_type pos;
  43. };
  44. inline bool valid(Index idx) const noexcept {
  45. return idx < reverse.size() && reverse[idx] < direct.size() && direct[reverse[idx]] == idx;
  46. }
  47. public:
  48. explicit SparseSet() = default;
  49. SparseSet(const SparseSet &) = delete;
  50. SparseSet(SparseSet &&) = default;
  51. virtual ~SparseSet() noexcept {
  52. assert(empty());
  53. }
  54. SparseSet & operator=(const SparseSet &) = delete;
  55. SparseSet & operator=(SparseSet &&) = default;
  56. bool empty() const noexcept {
  57. return direct.empty();
  58. }
  59. const index_type * data() const noexcept {
  60. return direct.data();
  61. }
  62. size_type size() const noexcept {
  63. return direct.size();
  64. }
  65. iterator_type begin() const noexcept {
  66. return SparseSetIterator{&direct, direct.size()};
  67. }
  68. iterator_type end() const noexcept {
  69. return SparseSetIterator{&direct, 0};
  70. }
  71. bool has(index_type idx) const noexcept {
  72. return valid(idx);
  73. }
  74. pos_type get(index_type idx) const noexcept {
  75. assert(valid(idx));
  76. return reverse[idx];
  77. }
  78. pos_type construct(index_type idx) {
  79. assert(!valid(idx));
  80. if(!(idx < reverse.size())) {
  81. reverse.resize(idx+1);
  82. }
  83. auto pos = pos_type(direct.size());
  84. reverse[idx] = pos;
  85. direct.emplace_back(idx);
  86. return pos;
  87. }
  88. pos_type destroy(index_type idx) {
  89. assert(valid(idx));
  90. auto last = direct.size() - 1;
  91. auto pos = reverse[idx];
  92. reverse[direct[last]] = pos;
  93. direct[pos] = direct[last];
  94. direct.pop_back();
  95. return pos;
  96. }
  97. void reset() {
  98. reverse.resize(0);
  99. direct.clear();
  100. }
  101. private:
  102. std::vector<pos_type> reverse;
  103. std::vector<index_type> direct;
  104. };
  105. template<typename Index, typename Type>
  106. class SparseSet<Index, Type> final: public SparseSet<Index> {
  107. public:
  108. using type = Type;
  109. using index_type = typename SparseSet<Index>::index_type;
  110. using pos_type = typename SparseSet<Index>::pos_type;
  111. using size_type = typename SparseSet<Index>::size_type;
  112. using iterator_type = typename SparseSet<Index>::iterator_type;
  113. explicit SparseSet() = default;
  114. SparseSet(const SparseSet &) = delete;
  115. SparseSet(SparseSet &&) = default;
  116. SparseSet & operator=(const SparseSet &) = delete;
  117. SparseSet & operator=(SparseSet &&) = default;
  118. type * raw() noexcept {
  119. return instances.data();
  120. }
  121. const type * raw() const noexcept {
  122. return instances.data();
  123. }
  124. const type & get(index_type idx) const noexcept {
  125. return instances[SparseSet<Index>::get(idx)];
  126. }
  127. type & get(index_type idx) noexcept {
  128. return const_cast<type &>(const_cast<const SparseSet *>(this)->get(idx));
  129. }
  130. template<typename... Args>
  131. type & construct(index_type idx, Args... args) {
  132. SparseSet<Index>::construct(idx);
  133. instances.push_back({ args... });
  134. return instances.back();
  135. }
  136. void destroy(index_type idx) {
  137. auto pos = SparseSet<Index>::destroy(idx);
  138. instances[pos] = std::move(instances[SparseSet<Index>::size()]);
  139. instances.pop_back();
  140. }
  141. void reset() {
  142. SparseSet<Index>::reset();
  143. instances.clear();
  144. }
  145. private:
  146. std::vector<type> instances;
  147. };
  148. }
  149. #endif // ENTT_COMPONENT_POOL_HPP