EnTT  3.10.0
storage.hpp
1 #ifndef ENTT_ENTITY_STORAGE_HPP
2 #define ENTT_ENTITY_STORAGE_HPP
3 
4 #include <cstddef>
5 #include <iterator>
6 #include <memory>
7 #include <tuple>
8 #include <type_traits>
9 #include <utility>
10 #include <vector>
11 #include "../config/config.h"
12 #include "../core/compressed_pair.hpp"
13 #include "../core/iterator.hpp"
14 #include "../core/memory.hpp"
15 #include "../core/type_info.hpp"
16 #include "component.hpp"
17 #include "entity.hpp"
18 #include "fwd.hpp"
19 #include "sigh_storage_mixin.hpp"
20 #include "sparse_set.hpp"
21 
22 namespace entt {
23 
29 namespace internal {
30 
31 template<typename Container>
32 class storage_iterator final {
33  friend storage_iterator<const Container>;
34 
35  using container_type = std::remove_const_t<Container>;
36  using alloc_traits = std::allocator_traits<typename container_type::allocator_type>;
37  using comp_traits = component_traits<typename container_type::value_type>;
38 
39  using iterator_traits = std::iterator_traits<std::conditional_t<
40  std::is_const_v<Container>,
41  typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer,
42  typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>>;
43 
44 public:
45  using value_type = typename iterator_traits::value_type;
46  using pointer = typename iterator_traits::pointer;
47  using reference = typename iterator_traits::reference;
48  using difference_type = typename iterator_traits::difference_type;
49  using iterator_category = std::random_access_iterator_tag;
50 
51  storage_iterator() ENTT_NOEXCEPT = default;
52 
53  storage_iterator(Container *ref, difference_type idx) ENTT_NOEXCEPT
54  : packed{ref},
55  offset{idx} {}
56 
57  template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>>
58  storage_iterator(const storage_iterator<std::remove_const_t<Container>> &other) ENTT_NOEXCEPT
59  : packed{other.packed},
60  offset{other.offset} {}
61 
62  storage_iterator &operator++() ENTT_NOEXCEPT {
63  return --offset, *this;
64  }
65 
66  storage_iterator operator++(int) ENTT_NOEXCEPT {
67  storage_iterator orig = *this;
68  return ++(*this), orig;
69  }
70 
71  storage_iterator &operator--() ENTT_NOEXCEPT {
72  return ++offset, *this;
73  }
74 
75  storage_iterator operator--(int) ENTT_NOEXCEPT {
76  storage_iterator orig = *this;
77  return operator--(), orig;
78  }
79 
80  storage_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
81  offset -= value;
82  return *this;
83  }
84 
85  storage_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
86  storage_iterator copy = *this;
87  return (copy += value);
88  }
89 
90  storage_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
91  return (*this += -value);
92  }
93 
94  storage_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
95  return (*this + -value);
96  }
97 
98  [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
99  const auto pos = index() - value;
100  return (*packed)[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
101  }
102 
103  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
104  const auto pos = index();
105  return (*packed)[pos / comp_traits::page_size] + fast_mod(pos, comp_traits::page_size);
106  }
107 
108  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
109  return *operator->();
110  }
111 
112  [[nodiscard]] difference_type index() const ENTT_NOEXCEPT {
113  return offset - 1;
114  }
115 
116 private:
117  Container *packed;
118  difference_type offset;
119 };
120 
121 template<typename CLhs, typename CRhs>
122 [[nodiscard]] std::ptrdiff_t operator-(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
123  return rhs.index() - lhs.index();
124 }
125 
126 template<typename CLhs, typename CRhs>
127 [[nodiscard]] bool operator==(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
128  return lhs.index() == rhs.index();
129 }
130 
131 template<typename CLhs, typename CRhs>
132 [[nodiscard]] bool operator!=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
133  return !(lhs == rhs);
134 }
135 
136 template<typename CLhs, typename CRhs>
137 [[nodiscard]] bool operator<(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
138  return lhs.index() > rhs.index();
139 }
140 
141 template<typename CLhs, typename CRhs>
142 [[nodiscard]] bool operator>(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
143  return lhs.index() < rhs.index();
144 }
145 
146 template<typename CLhs, typename CRhs>
147 [[nodiscard]] bool operator<=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
148  return !(lhs > rhs);
149 }
150 
151 template<typename CLhs, typename CRhs>
152 [[nodiscard]] bool operator>=(const storage_iterator<CLhs> &lhs, const storage_iterator<CRhs> &rhs) ENTT_NOEXCEPT {
153  return !(lhs < rhs);
154 }
155 
156 template<typename It, typename... Other>
157 class extended_storage_iterator final {
158  template<typename Iter, typename... Args>
159  friend class extended_storage_iterator;
160 
161 public:
162  using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::forward_as_tuple(*std::declval<Other>()...)));
163  using pointer = input_iterator_pointer<value_type>;
164  using reference = value_type;
165  using difference_type = std::ptrdiff_t;
166  using iterator_category = std::input_iterator_tag;
167 
168  extended_storage_iterator() = default;
169 
170  extended_storage_iterator(It base, Other... other)
171  : it{base, other...} {}
172 
173  template<typename... Args, typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>>
174  extended_storage_iterator(const extended_storage_iterator<It, Args...> &other)
175  : it{other.it} {}
176 
177  extended_storage_iterator &operator++() ENTT_NOEXCEPT {
178  return ++std::get<It>(it), (++std::get<Other>(it), ...), *this;
179  }
180 
181  extended_storage_iterator operator++(int) ENTT_NOEXCEPT {
182  extended_storage_iterator orig = *this;
183  return ++(*this), orig;
184  }
185 
186  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
187  return operator*();
188  }
189 
190  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
191  return {*std::get<It>(it), *std::get<Other>(it)...};
192  }
193 
194  template<typename... CLhs, typename... CRhs>
195  friend bool operator==(const extended_storage_iterator<CLhs...> &, const extended_storage_iterator<CRhs...> &) ENTT_NOEXCEPT;
196 
197 private:
198  std::tuple<It, Other...> it;
199 };
200 
201 template<typename... CLhs, typename... CRhs>
202 [[nodiscard]] bool operator==(const extended_storage_iterator<CLhs...> &lhs, const extended_storage_iterator<CRhs...> &rhs) ENTT_NOEXCEPT {
203  return std::get<0>(lhs.it) == std::get<0>(rhs.it);
204 }
205 
206 template<typename... CLhs, typename... CRhs>
207 [[nodiscard]] bool operator!=(const extended_storage_iterator<CLhs...> &lhs, const extended_storage_iterator<CRhs...> &rhs) ENTT_NOEXCEPT {
208  return !(lhs == rhs);
209 }
210 
211 } // namespace internal
212 
233 template<typename Entity, typename Type, typename Allocator, typename>
234 class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
235  static_assert(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>, "The type must be at least move constructible/assignable");
236 
237  using alloc_traits = std::allocator_traits<Allocator>;
238  static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
240  using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
242 
243  [[nodiscard]] auto &element_at(const std::size_t pos) const {
244  return packed.first()[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
245  }
246 
247  auto assure_at_least(const std::size_t pos) {
248  auto &&container = packed.first();
249  const auto idx = pos / comp_traits::page_size;
250 
251  if(!(idx < container.size())) {
252  auto curr = container.size();
253  container.resize(idx + 1u, nullptr);
254 
255  ENTT_TRY {
256  for(const auto last = container.size(); curr < last; ++curr) {
257  container[curr] = alloc_traits::allocate(packed.second(), comp_traits::page_size);
258  }
259  }
260  ENTT_CATCH {
261  container.resize(curr);
262  ENTT_THROW;
263  }
264  }
265 
266  return container[idx] + fast_mod(pos, comp_traits::page_size);
267  }
268 
269  template<typename... Args>
270  auto emplace_element(const Entity entt, const bool force_back, Args &&...args) {
271  const auto it = base_type::try_emplace(entt, force_back);
272 
273  ENTT_TRY {
274  auto elem = assure_at_least(static_cast<size_type>(it.index()));
275  entt::uninitialized_construct_using_allocator(to_address(elem), packed.second(), std::forward<Args>(args)...);
276  }
277  ENTT_CATCH {
278  if constexpr(comp_traits::in_place_delete) {
279  base_type::in_place_pop(it, it + 1u);
280  } else {
281  base_type::swap_and_pop(it, it + 1u);
282  }
283 
284  ENTT_THROW;
285  }
286 
287  return it;
288  }
289 
290  void shrink_to_size(const std::size_t sz) {
291  for(auto pos = sz, length = base_type::size(); pos < length; ++pos) {
292  if constexpr(comp_traits::in_place_delete) {
293  if(base_type::at(pos) != tombstone) {
294  std::destroy_at(std::addressof(element_at(pos)));
295  }
296  } else {
297  std::destroy_at(std::addressof(element_at(pos)));
298  }
299  }
300 
301  auto &&container = packed.first();
302  auto page_allocator{packed.second()};
303  const auto from = (sz + comp_traits::page_size - 1u) / comp_traits::page_size;
304 
305  for(auto pos = from, last = container.size(); pos < last; ++pos) {
306  alloc_traits::deallocate(page_allocator, container[pos], comp_traits::page_size);
307  }
308 
309  container.resize(from);
310  }
311 
312 private:
313  const void *get_at(const std::size_t pos) const final {
314  return std::addressof(element_at(pos));
315  }
316 
317  void swap_at(const std::size_t lhs, const std::size_t rhs) final {
318  using std::swap;
319  swap(element_at(lhs), element_at(rhs));
320  }
321 
322  void move_element(const std::size_t from, const std::size_t to) final {
323  auto &elem = element_at(from);
324  entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), packed.second(), std::move(elem));
325  std::destroy_at(std::addressof(elem));
326  }
327 
328 protected:
334  void swap_and_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override {
335  for(; first != last; ++first) {
336  auto &elem = element_at(base_type::size() - 1u);
337  // destroying on exit allows reentrant destructors
338  [[maybe_unused]] auto unused = std::exchange(element_at(static_cast<size_type>(first.index())), std::move(elem));
339  std::destroy_at(std::addressof(elem));
340  base_type::swap_and_pop(first, first + 1u);
341  }
342  }
343 
349  void in_place_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override {
350  for(; first != last; ++first) {
351  base_type::in_place_pop(first, first + 1u);
352  std::destroy_at(std::addressof(element_at(static_cast<size_type>(first.index()))));
353  }
354  }
355 
363  typename underlying_type::basic_iterator try_emplace([[maybe_unused]] const Entity entt, const bool force_back, const void *value) override {
364  if(value) {
365  if constexpr(std::is_copy_constructible_v<value_type>) {
366  return emplace_element(entt, force_back, *static_cast<const value_type *>(value));
367  } else {
368  return base_type::end();
369  }
370  } else {
371  if constexpr(std::is_default_constructible_v<value_type>) {
372  return emplace_element(entt, force_back);
373  } else {
374  return base_type::end();
375  }
376  }
377  }
378 
379 public:
383  using allocator_type = Allocator;
385  using value_type = Type;
387  using entity_type = Entity;
389  using size_type = std::size_t;
391  using pointer = typename container_type::pointer;
393  using const_pointer = typename alloc_traits::template rebind_traits<typename alloc_traits::const_pointer>::const_pointer;
395  using iterator = internal::storage_iterator<container_type>;
397  using const_iterator = internal::storage_iterator<const container_type>;
399  using reverse_iterator = std::reverse_iterator<iterator>;
401  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
406 
410 
415  explicit basic_storage(const allocator_type &allocator)
416  : base_type{type_id<value_type>(), deletion_policy{comp_traits::in_place_delete}, allocator},
417  packed{container_type{allocator}, allocator} {}
418 
423  basic_storage(basic_storage &&other) ENTT_NOEXCEPT
424  : base_type{std::move(other)},
425  packed{std::move(other.packed)} {}
426 
432  basic_storage(basic_storage &&other, const allocator_type &allocator) ENTT_NOEXCEPT
433  : base_type{std::move(other), allocator},
434  packed{container_type{std::move(other.packed.first()), allocator}, allocator} {
435  ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed");
436  }
437 
439  ~basic_storage() override {
440  shrink_to_size(0u);
441  }
442 
448  basic_storage &operator=(basic_storage &&other) ENTT_NOEXCEPT {
449  ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.second() == other.packed.second(), "Copying a storage is not allowed");
450 
451  shrink_to_size(0u);
452  base_type::operator=(std::move(other));
453  packed.first() = std::move(other.packed.first());
454  propagate_on_container_move_assignment(packed.second(), other.packed.second());
455  return *this;
456  }
457 
462  void swap(basic_storage &other) {
463  using std::swap;
464  underlying_type::swap(other);
465  propagate_on_container_swap(packed.second(), other.packed.second());
466  swap(packed.first(), other.packed.first());
467  }
468 
473  [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
474  return allocator_type{packed.second()};
475  }
476 
485  void reserve(const size_type cap) override {
486  if(cap != 0u) {
487  base_type::reserve(cap);
488  assure_at_least(cap - 1u);
489  }
490  }
491 
497  [[nodiscard]] size_type capacity() const ENTT_NOEXCEPT override {
498  return packed.first().size() * comp_traits::page_size;
499  }
500 
502  void shrink_to_fit() override {
504  shrink_to_size(base_type::size());
505  }
506 
511  [[nodiscard]] const_pointer raw() const ENTT_NOEXCEPT {
512  return packed.first().data();
513  }
514 
516  [[nodiscard]] pointer raw() ENTT_NOEXCEPT {
517  return packed.first().data();
518  }
519 
528  [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
529  const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
530  return const_iterator{&packed.first(), pos};
531  }
532 
534  [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
535  return cbegin();
536  }
537 
539  [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
540  const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
541  return iterator{&packed.first(), pos};
542  }
543 
554  [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
555  return const_iterator{&packed.first(), {}};
556  }
557 
559  [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
560  return cend();
561  }
562 
564  [[nodiscard]] iterator end() ENTT_NOEXCEPT {
565  return iterator{&packed.first(), {}};
566  }
567 
577  [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT {
578  return std::make_reverse_iterator(cend());
579  }
580 
582  [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
583  return crbegin();
584  }
585 
587  [[nodiscard]] reverse_iterator rbegin() ENTT_NOEXCEPT {
588  return std::make_reverse_iterator(end());
589  }
590 
601  [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT {
602  return std::make_reverse_iterator(cbegin());
603  }
604 
606  [[nodiscard]] const_reverse_iterator rend() const ENTT_NOEXCEPT {
607  return crend();
608  }
609 
611  [[nodiscard]] reverse_iterator rend() ENTT_NOEXCEPT {
612  return std::make_reverse_iterator(begin());
613  }
614 
625  [[nodiscard]] const value_type &get(const entity_type entt) const ENTT_NOEXCEPT {
626  return element_at(base_type::index(entt));
627  }
628 
630  [[nodiscard]] value_type &get(const entity_type entt) ENTT_NOEXCEPT {
631  return const_cast<value_type &>(std::as_const(*this).get(entt));
632  }
633 
639  [[nodiscard]] std::tuple<const value_type &> get_as_tuple(const entity_type entt) const ENTT_NOEXCEPT {
640  return std::forward_as_tuple(get(entt));
641  }
642 
644  [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) ENTT_NOEXCEPT {
645  return std::forward_as_tuple(get(entt));
646  }
647 
660  template<typename... Args>
661  value_type &emplace(const entity_type entt, Args &&...args) {
662  if constexpr(std::is_aggregate_v<value_type>) {
663  const auto it = emplace_element(entt, false, Type{std::forward<Args>(args)...});
664  return element_at(static_cast<size_type>(it.index()));
665  } else {
666  const auto it = emplace_element(entt, false, std::forward<Args>(args)...);
667  return element_at(static_cast<size_type>(it.index()));
668  }
669  }
670 
678  template<typename... Func>
679  value_type &patch(const entity_type entt, Func &&...func) {
680  const auto idx = base_type::index(entt);
681  auto &elem = element_at(idx);
682  (std::forward<Func>(func)(elem), ...);
683  return elem;
684  }
685 
699  template<typename It>
700  void insert(It first, It last, const value_type &value = {}) {
701  for(; first != last; ++first) {
702  emplace_element(*first, true, value);
703  }
704  }
705 
718  template<typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, value_type>>>
719  void insert(EIt first, EIt last, CIt from) {
720  for(; first != last; ++first, ++from) {
721  emplace_element(*first, true, *from);
722  }
723  }
724 
733  [[nodiscard]] iterable each() ENTT_NOEXCEPT {
734  return {internal::extended_storage_iterator{base_type::begin(), begin()}, internal::extended_storage_iterator{base_type::end(), end()}};
735  }
736 
738  [[nodiscard]] const_iterable each() const ENTT_NOEXCEPT {
739  return {internal::extended_storage_iterator{base_type::cbegin(), cbegin()}, internal::extended_storage_iterator{base_type::cend(), cend()}};
740  }
741 
742 private:
744 };
745 
747 template<typename Entity, typename Type, typename Allocator>
748 class basic_storage<Entity, Type, Allocator, std::enable_if_t<ignore_as_empty_v<Type>>>
749  : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
750  using alloc_traits = std::allocator_traits<Allocator>;
751  static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
754 
755 public:
759  using allocator_type = Allocator;
761  using value_type = Type;
763  using entity_type = Entity;
765  using size_type = std::size_t;
770 
774 
779  explicit basic_storage(const allocator_type &allocator)
780  : base_type{type_id<value_type>(), deletion_policy{comp_traits::in_place_delete}, allocator} {}
781 
786  basic_storage(basic_storage &&other) ENTT_NOEXCEPT = default;
787 
793  basic_storage(basic_storage &&other, const allocator_type &allocator) ENTT_NOEXCEPT
794  : base_type{std::move(other), allocator} {}
795 
801  basic_storage &operator=(basic_storage &&other) ENTT_NOEXCEPT = default;
802 
807  [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
809  }
810 
820  void get([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
821  ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity");
822  }
823 
834  [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
835  ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity");
836  return std::tuple{};
837  }
838 
849  template<typename... Args>
850  void emplace(const entity_type entt, Args &&...) {
852  }
853 
860  template<typename... Func>
861  void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
862  ENTT_ASSERT(base_type::contains(entt), "Storage does not contain entity");
863  (std::forward<Func>(func)(), ...);
864  }
865 
873  template<typename It, typename... Args>
874  void insert(It first, It last, Args &&...) {
875  for(; first != last; ++first) {
876  base_type::try_emplace(*first, true);
877  }
878  }
879 
887  [[nodiscard]] iterable each() ENTT_NOEXCEPT {
888  return {internal::extended_storage_iterator{base_type::begin()}, internal::extended_storage_iterator{base_type::end()}};
889  }
890 
892  [[nodiscard]] const_iterable each() const ENTT_NOEXCEPT {
893  return {internal::extended_storage_iterator{base_type::cbegin()}, internal::extended_storage_iterator{base_type::cend()}};
894  }
895 };
896 
902 template<typename Entity, typename Type, typename = void>
906 };
907 
908 } // namespace entt
909 
910 #endif
Basic sparse set implementation.
Definition: sparse_set.hpp:174
void swap(basic_sparse_set &other)
Exchanges the contents with those of a given sparse set.
Definition: sparse_set.hpp:390
size_type index(const entity_type entt) const
Returns the position of an entity in a sparse set.
Definition: sparse_set.hpp:605
virtual basic_iterator try_emplace(const Entity entt, const bool force_back, const void *=nullptr)
Assigns an entity to a sparse set.
Definition: sparse_set.hpp:271
iterator end() const
Returns an iterator to the end.
Definition: sparse_set.hpp:514
virtual void reserve(const size_type cap)
Increases the capacity of a sparse set.
Definition: sparse_set.hpp:423
size_type size() const
Returns the number of elements in a sparse set.
Definition: sparse_set.hpp:465
virtual void shrink_to_fit()
Requests the removal of unused capacity.
Definition: sparse_set.hpp:437
virtual void swap_and_pop(basic_iterator first, basic_iterator last)
Erases entities from a sparse set.
Definition: sparse_set.hpp:241
entity_type at(const size_type pos) const
Returns the entity at specified location, with bounds checking.
Definition: sparse_set.hpp:615
const_iterator begin() const
Returns an iterator to the beginning.
Definition: sparse_set.hpp:494
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition: sparse_set.hpp:500
internal::sparse_set_iterator< packed_container_type > basic_iterator
Random access iterator type.
Definition: sparse_set.hpp:234
bool contains(const entity_type entt) const
Checks if a sparse set contains an entity.
Definition: sparse_set.hpp:576
constexpr allocator_type get_allocator() const
Returns the associated allocator.
Definition: sparse_set.hpp:403
const_iterator cend() const
Returns an iterator to the end.
Definition: sparse_set.hpp:519
basic_sparse_set & operator=(basic_sparse_set &&other)
Move assignment operator.
Definition: sparse_set.hpp:374
virtual void in_place_pop(basic_iterator first, basic_iterator last)
Erases entities from a sparse set.
Definition: sparse_set.hpp:258
basic_storage(const allocator_type &allocator)
Constructs an empty container with a given allocator.
Definition: storage.hpp:779
basic_storage(basic_storage &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition: storage.hpp:793
constexpr allocator_type get_allocator() const
Returns the associated allocator.
Definition: storage.hpp:807
const_iterable each() const
Returns an iterable object to use to visit a storage.
Definition: storage.hpp:892
iterable each()
Returns an iterable object to use to visit a storage.
Definition: storage.hpp:887
void insert(It first, It last, Args &&...)
Assigns entities to a storage.
Definition: storage.hpp:874
std::tuple get_as_tuple([[maybe_unused]] const entity_type entt) const
Returns an empty tuple.
Definition: storage.hpp:834
void patch([[maybe_unused]] const entity_type entt, Func &&...func)
Updates the instance assigned to a given entity in-place.
Definition: storage.hpp:861
void get([[maybe_unused]] const entity_type entt) const
Returns the object assigned to an entity, that is void.
Definition: storage.hpp:820
void emplace(const entity_type entt, Args &&...)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:850
basic_storage & operator=(basic_storage &&other)=default
Move assignment operator.
Basic storage implementation.
Definition: storage.hpp:234
value_type & get(const entity_type entt)
Returns the object assigned to an entity.
Definition: storage.hpp:630
const_reverse_iterator crend() const
Returns a reverse iterator to the end.
Definition: storage.hpp:601
void shrink_to_fit() override
Requests the removal of unused capacity.
Definition: storage.hpp:502
iterator end()
Returns an iterator to the end.
Definition: storage.hpp:564
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition: storage.hpp:528
const_iterator cend() const
Returns an iterator to the end.
Definition: storage.hpp:554
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
Definition: storage.hpp:399
const_reverse_iterator rbegin() const
Returns a reverse iterator to the beginning.
Definition: storage.hpp:582
Allocator allocator_type
Allocator type.
Definition: storage.hpp:383
basic_storage(basic_storage &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition: storage.hpp:432
underlying_type::basic_iterator try_emplace([[maybe_unused]] const Entity entt, const bool force_back, const void *value) override
Assigns an entity to a storage.
Definition: storage.hpp:363
std::tuple< value_type & > get_as_tuple(const entity_type entt)
Returns the object assigned to an entity as a tuple.
Definition: storage.hpp:644
iterable each()
Returns an iterable object to use to visit a storage.
Definition: storage.hpp:733
internal::storage_iterator< container_type > iterator
Random access iterator type.
Definition: storage.hpp:395
internal::storage_iterator< const container_type > const_iterator
Constant random access iterator type.
Definition: storage.hpp:397
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: storage.hpp:611
basic_storage & operator=(basic_storage &&other)
Move assignment operator.
Definition: storage.hpp:448
const_iterator begin() const
Returns an iterator to the beginning.
Definition: storage.hpp:534
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
Definition: storage.hpp:661
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: storage.hpp:587
const_pointer raw() const
Direct access to the array of objects.
Definition: storage.hpp:511
basic_storage(basic_storage &&other)
Move constructor.
Definition: storage.hpp:423
typename container_type::pointer pointer
Pointer type to contained elements.
Definition: storage.hpp:391
void reserve(const size_type cap) override
Increases the capacity of a storage.
Definition: storage.hpp:485
value_type & patch(const entity_type entt, Func &&...func)
Updates the instance assigned to a given entity in-place.
Definition: storage.hpp:679
void in_place_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override
Erases elements from a storage.
Definition: storage.hpp:349
const_reverse_iterator rend() const
Returns a reverse iterator to the end.
Definition: storage.hpp:606
std::size_t size_type
Unsigned integer type.
Definition: storage.hpp:389
std::reverse_iterator< const_iterator > const_reverse_iterator
Constant reverse iterator type.
Definition: storage.hpp:401
typename alloc_traits::template rebind_traits< typename alloc_traits::const_pointer >::const_pointer const_pointer
Constant pointer type to contained elements.
Definition: storage.hpp:393
const_reverse_iterator crbegin() const
Returns a reverse iterator to the beginning.
Definition: storage.hpp:577
basic_storage(const allocator_type &allocator)
Constructs an empty storage with a given allocator.
Definition: storage.hpp:415
const_iterator end() const
Returns an iterator to the end.
Definition: storage.hpp:559
pointer raw()
Direct access to the array of objects.
Definition: storage.hpp:516
Entity entity_type
Underlying entity identifier.
Definition: storage.hpp:387
void insert(It first, It last, const value_type &value={})
Assigns one or more entities to a storage and constructs their objects from a given instance.
Definition: storage.hpp:700
iterator begin()
Returns an iterator to the beginning.
Definition: storage.hpp:539
basic_storage()
Default constructor.
Definition: storage.hpp:408
void swap(basic_storage &other)
Exchanges the contents with those of a given storage.
Definition: storage.hpp:462
constexpr allocator_type get_allocator() const
Returns the associated allocator.
Definition: storage.hpp:473
void insert(EIt first, EIt last, CIt from)
Assigns one or more entities to a storage and constructs their objects from a given range.
Definition: storage.hpp:719
void swap_and_pop(typename underlying_type::basic_iterator first, typename underlying_type::basic_iterator last) override
Erases elements from a storage.
Definition: storage.hpp:334
~basic_storage() override
Default destructor.
Definition: storage.hpp:439
const_iterable each() const
Returns an iterable object to use to visit a storage.
Definition: storage.hpp:738
Type value_type
Type of the objects assigned to entities.
Definition: storage.hpp:385
std::tuple< const value_type & > get_as_tuple(const entity_type entt) const
Returns the object assigned to an entity as a tuple.
Definition: storage.hpp:639
const value_type & get(const entity_type entt) const
Returns the object assigned to an entity.
Definition: storage.hpp:625
size_type capacity() const override
Returns the number of elements that a storage has currently allocated space for.
Definition: storage.hpp:497
second_type & second()
Returns the second element that a pair stores.
first_type & first()
Returns the first element that a pair stores.
Mixin type used to add signal support to storage types.
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 void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs)
Utility function to design allocation-aware containers.
Definition: memory.hpp:49
constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs)
Utility function to design allocation-aware containers.
Definition: memory.hpp:62
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
const type_info & type_id()
Returns the type info object associated to a given type.
Definition: type_info.hpp:257
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 Type * uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition: memory.hpp:283
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 auto to_address(Type &&ptr)
Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
Definition: memory.hpp:21
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
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.
Common way to access various properties of components.
Definition: component.hpp:43
static constexpr std::size_t page_size
Page size, default is ENTT_PACKED_PAGE for non-empty types.
Definition: component.hpp:49
static constexpr bool in_place_delete
Pointer stability, default is false.
Definition: component.hpp:47
Utility class to create an iterable object from a pair of iterators.
Definition: iterator.hpp:63
Provides a common way to access certain properties of storage types.
Definition: storage.hpp:903