EnTT 3.14.0
Loading...
Searching...
No Matches
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/bit.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 "sparse_set.hpp"
20
21namespace entt {
22
24namespace internal {
25
26template<typename Container>
27class storage_iterator final {
28 friend storage_iterator<const Container>;
29
30 using container_type = std::remove_const_t<Container>;
31 using alloc_traits = std::allocator_traits<typename container_type::allocator_type>;
32
33 using iterator_traits = std::iterator_traits<std::conditional_t<
34 std::is_const_v<Container>,
35 typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer,
36 typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>>;
37
38public:
39 using value_type = typename iterator_traits::value_type;
40 using pointer = typename iterator_traits::pointer;
41 using reference = typename iterator_traits::reference;
42 using difference_type = typename iterator_traits::difference_type;
43 using iterator_category = std::random_access_iterator_tag;
44
45 constexpr storage_iterator() noexcept = default;
46
47 constexpr storage_iterator(Container *ref, const difference_type idx) noexcept
48 : payload{ref},
49 offset{idx} {}
50
51 template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>>
52 constexpr storage_iterator(const storage_iterator<std::remove_const_t<Container>> &other) noexcept
53 : storage_iterator{other.payload, other.offset} {}
54
55 constexpr storage_iterator &operator++() noexcept {
56 return --offset, *this;
57 }
58
59 constexpr storage_iterator operator++(int) noexcept {
60 storage_iterator orig = *this;
61 return ++(*this), orig;
62 }
63
64 constexpr storage_iterator &operator--() noexcept {
65 return ++offset, *this;
66 }
67
68 constexpr storage_iterator operator--(int) noexcept {
69 storage_iterator orig = *this;
70 return operator--(), orig;
71 }
72
73 constexpr storage_iterator &operator+=(const difference_type value) noexcept {
74 offset -= value;
75 return *this;
76 }
77
78 constexpr storage_iterator operator+(const difference_type value) const noexcept {
79 storage_iterator copy = *this;
80 return (copy += value);
81 }
82
83 constexpr storage_iterator &operator-=(const difference_type value) noexcept {
84 return (*this += -value);
85 }
86
87 constexpr storage_iterator operator-(const difference_type value) const noexcept {
88 return (*this + -value);
89 }
90
91 [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
92 const auto pos = index() - value;
93 constexpr auto page_size = component_traits<value_type>::page_size;
94 return (*payload)[pos / page_size][fast_mod(static_cast<std::size_t>(pos), page_size)];
95 }
96
97 [[nodiscard]] constexpr pointer operator->() const noexcept {
98 return std::addressof(operator[](0));
99 }
100
101 [[nodiscard]] constexpr reference operator*() const noexcept {
102 return operator[](0);
103 }
104
105 [[nodiscard]] constexpr difference_type index() const noexcept {
106 return offset - 1;
107 }
108
109private:
110 Container *payload;
111 difference_type offset;
112};
113
114template<typename Lhs, typename Rhs>
115[[nodiscard]] constexpr std::ptrdiff_t operator-(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
116 return rhs.index() - lhs.index();
117}
118
119template<typename Lhs, typename Rhs>
120[[nodiscard]] constexpr bool operator==(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
121 return lhs.index() == rhs.index();
122}
123
124template<typename Lhs, typename Rhs>
125[[nodiscard]] constexpr bool operator!=(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
126 return !(lhs == rhs);
127}
128
129template<typename Lhs, typename Rhs>
130[[nodiscard]] constexpr bool operator<(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
131 return lhs.index() > rhs.index();
132}
133
134template<typename Lhs, typename Rhs>
135[[nodiscard]] constexpr bool operator>(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
136 return rhs < lhs;
137}
138
139template<typename Lhs, typename Rhs>
140[[nodiscard]] constexpr bool operator<=(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
141 return !(lhs > rhs);
142}
143
144template<typename Lhs, typename Rhs>
145[[nodiscard]] constexpr bool operator>=(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept {
146 return !(lhs < rhs);
147}
148
149template<typename It, typename... Other>
150class extended_storage_iterator final {
151 template<typename Iter, typename... Args>
152 friend class extended_storage_iterator;
153
154public:
155 using iterator_type = It;
156 using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::forward_as_tuple(*std::declval<Other>()...)));
157 using pointer = input_iterator_pointer<value_type>;
158 using reference = value_type;
159 using difference_type = std::ptrdiff_t;
160 using iterator_category = std::input_iterator_tag;
161 using iterator_concept = std::forward_iterator_tag;
162
163 constexpr extended_storage_iterator()
164 : it{} {}
165
166 constexpr extended_storage_iterator(iterator_type base, Other... other)
167 : it{base, other...} {}
168
169 template<typename... Args, typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>>
170 constexpr extended_storage_iterator(const extended_storage_iterator<It, Args...> &other)
171 : it{other.it} {}
172
173 constexpr extended_storage_iterator &operator++() noexcept {
174 return ++std::get<It>(it), (++std::get<Other>(it), ...), *this;
175 }
176
177 constexpr extended_storage_iterator operator++(int) noexcept {
178 extended_storage_iterator orig = *this;
179 return ++(*this), orig;
180 }
181
182 [[nodiscard]] constexpr pointer operator->() const noexcept {
183 return operator*();
184 }
185
186 [[nodiscard]] constexpr reference operator*() const noexcept {
187 return {*std::get<It>(it), *std::get<Other>(it)...};
188 }
189
190 [[nodiscard]] constexpr iterator_type base() const noexcept {
191 return std::get<It>(it);
192 }
193
194 template<typename... Lhs, typename... Rhs>
195 friend constexpr bool operator==(const extended_storage_iterator<Lhs...> &, const extended_storage_iterator<Rhs...> &) noexcept;
196
197private:
198 std::tuple<It, Other...> it;
199};
200
201template<typename... Lhs, typename... Rhs>
202[[nodiscard]] constexpr bool operator==(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept {
203 return std::get<0>(lhs.it) == std::get<0>(rhs.it);
204}
205
206template<typename... Lhs, typename... Rhs>
207[[nodiscard]] constexpr bool operator!=(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept {
208 return !(lhs == rhs);
209}
210
211} // namespace internal
229template<typename Type, typename Entity, typename Allocator, typename>
230class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
231 using alloc_traits = std::allocator_traits<Allocator>;
232 static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
233 using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
235 using underlying_iterator = typename underlying_type::basic_iterator;
237
238 [[nodiscard]] auto &element_at(const std::size_t pos) const {
240 }
241
242 auto assure_at_least(const std::size_t pos) {
243 const auto idx = pos / traits_type::page_size;
244
245 if(!(idx < payload.size())) {
246 auto curr = payload.size();
248 payload.resize(idx + 1u, nullptr);
249
250 ENTT_TRY {
251 for(const auto last = payload.size(); curr < last; ++curr) {
252 payload[curr] = alloc_traits::allocate(allocator, traits_type::page_size);
253 }
254 }
255 ENTT_CATCH {
256 payload.resize(curr);
257 ENTT_THROW;
258 }
259 }
260
261 return payload[idx] + fast_mod(pos, traits_type::page_size);
262 }
263
264 template<typename... Args>
265 auto emplace_element(const Entity entt, const bool force_back, Args &&...args) {
267
268 ENTT_TRY {
269 auto *elem = to_address(assure_at_least(static_cast<size_type>(it.index())));
271 }
272 ENTT_CATCH {
273 base_type::pop(it, it + 1u);
274 ENTT_THROW;
275 }
276
277 return it;
278 }
279
280 void shrink_to_size(const std::size_t sz) {
283
284 for(auto pos = sz, length = base_type::size(); pos < length; ++pos) {
285 if constexpr(traits_type::in_place_delete) {
286 if(base_type::data()[pos] != tombstone) {
287 alloc_traits::destroy(allocator, std::addressof(element_at(pos)));
288 }
289 } else {
290 alloc_traits::destroy(allocator, std::addressof(element_at(pos)));
291 }
292 }
293
294 for(auto pos = from, last = payload.size(); pos < last; ++pos) {
295 alloc_traits::deallocate(allocator, payload[pos], traits_type::page_size);
296 }
297
298 payload.resize(from);
299 }
300
301private:
302 [[nodiscard]] const void *get_at(const std::size_t pos) const final {
303 return std::addressof(element_at(pos));
304 }
305
306 void swap_or_move([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) override {
307 static constexpr bool is_pinned_type_v = !(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>);
308 // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy
309 ENTT_ASSERT((from + 1u) && !is_pinned_type_v, "Pinned type");
310
311 if constexpr(!is_pinned_type_v) {
312 auto &elem = element_at(from);
313
314 if constexpr(traits_type::in_place_delete) {
315 if(base_type::operator[](to) == tombstone) {
318 alloc_traits::destroy(allocator, std::addressof(elem));
319 return;
320 }
321 }
322
323 using std::swap;
324 swap(elem, element_at(to));
325 }
326 }
327
328protected:
334 void pop(underlying_iterator first, underlying_iterator last) override {
335 for(allocator_type allocator{get_allocator()}; first != last; ++first) {
336 // cannot use first.index() because it would break with cross iterators
337 auto &elem = element_at(base_type::index(*first));
338
339 if constexpr(traits_type::in_place_delete) {
341 alloc_traits::destroy(allocator, std::addressof(elem));
342 } else {
343 auto &other = element_at(base_type::size() - 1u);
344 // destroying on exit allows reentrant destructors
345 [[maybe_unused]] auto unused = std::exchange(elem, std::move(other));
346 alloc_traits::destroy(allocator, std::addressof(other));
348 }
349 }
350 }
351
353 void pop_all() override {
355
356 for(auto first = base_type::begin(); !(first.index() < 0); ++first) {
357 if constexpr(traits_type::in_place_delete) {
358 if(*first != tombstone) {
360 alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index()))));
361 }
362 } else {
364 alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index()))));
365 }
366 }
367 }
368
376 underlying_iterator try_emplace([[maybe_unused]] const Entity entt, [[maybe_unused]] const bool force_back, const void *value) override {
377 if(value != nullptr) {
378 if constexpr(std::is_copy_constructible_v<element_type>) {
379 return emplace_element(entt, force_back, *static_cast<const element_type *>(value));
380 } else {
381 return base_type::end();
382 }
383 } else {
384 if constexpr(std::is_default_constructible_v<element_type>) {
385 return emplace_element(entt, force_back);
386 } else {
387 return base_type::end();
388 }
389 }
390 }
391
392public:
394 using allocator_type = Allocator;
398 using element_type = Type;
404 using size_type = std::size_t;
406 using pointer = typename container_type::pointer;
408 using const_pointer = typename alloc_traits::template rebind_traits<typename alloc_traits::const_pointer>::const_pointer;
410 using iterator = internal::storage_iterator<container_type>;
412 using const_iterator = internal::storage_iterator<const container_type>;
414 using reverse_iterator = std::reverse_iterator<iterator>;
416 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
427
431
439
441 basic_storage(const basic_storage &) = delete;
442
448 : base_type{std::move(other)},
449 payload{std::move(other.payload)} {}
450
457 : base_type{std::move(other), allocator},
458 payload{std::move(other.payload), allocator} {
459 // NOLINTNEXTLINE(bugprone-use-after-move)
460 ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed");
461 }
462
464 // NOLINTNEXTLINE(bugprone-exception-escape)
465 ~basic_storage() override {
466 shrink_to_size(0u);
467 }
468
474
481 ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed");
482 swap(other);
483 return *this;
484 }
485
490 void swap(basic_storage &other) noexcept {
491 using std::swap;
492 swap(payload, other.payload);
494 }
495
501 return payload.get_allocator();
502 }
503
512 void reserve(const size_type cap) override {
513 if(cap != 0u) {
515 assure_at_least(cap - 1u);
516 }
517 }
518
525 return payload.size() * traits_type::page_size;
526 }
527
529 void shrink_to_fit() override {
531 shrink_to_size(base_type::size());
532 }
533
539 return payload.data();
540 }
541
544 return payload.data();
545 }
546
555 const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
556 return const_iterator{&payload, pos};
557 }
558
561 return cbegin();
562 }
563
566 const auto pos = static_cast<typename iterator::difference_type>(base_type::size());
567 return iterator{&payload, pos};
568 }
569
576 return const_iterator{&payload, {}};
577 }
578
581 return cend();
582 }
583
586 return iterator{&payload, {}};
587 }
588
597 return std::make_reverse_iterator(cend());
598 }
599
604
607 return std::make_reverse_iterator(end());
608 }
609
616 return std::make_reverse_iterator(cbegin());
617 }
618
623
626 return std::make_reverse_iterator(begin());
627 }
628
639 [[nodiscard]] const value_type &get(const entity_type entt) const noexcept {
640 return element_at(base_type::index(entt));
641 }
642
644 [[nodiscard]] value_type &get(const entity_type entt) noexcept {
645 return const_cast<value_type &>(std::as_const(*this).get(entt));
646 }
647
653 [[nodiscard]] std::tuple<const value_type &> get_as_tuple(const entity_type entt) const noexcept {
654 return std::forward_as_tuple(get(entt));
655 }
656
658 [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) noexcept {
659 return std::forward_as_tuple(get(entt));
660 }
661
674 template<typename... Args>
676 if constexpr(std::is_aggregate_v<value_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<value_type>)) {
677 const auto it = emplace_element(entt, false, Type{std::forward<Args>(args)...});
678 return element_at(static_cast<size_type>(it.index()));
679 } else {
680 const auto it = emplace_element(entt, false, std::forward<Args>(args)...);
681 return element_at(static_cast<size_type>(it.index()));
682 }
683 }
684
692 template<typename... Func>
693 value_type &patch(const entity_type entt, Func &&...func) {
694 const auto idx = base_type::index(entt);
695 auto &elem = element_at(idx);
696 (std::forward<Func>(func)(elem), ...);
697 return elem;
698 }
699
714 template<typename It>
715 iterator insert(It first, It last, const value_type &value = {}) {
716 for(; first != last; ++first) {
717 emplace_element(*first, true, value);
718 }
719
720 return begin();
721 }
722
737 iterator insert(EIt first, EIt last, CIt from) {
738 for(; first != last; ++first, ++from) {
739 emplace_element(*first, true, *from);
740 }
741
742 return begin();
743 }
744
756
761
772
777
778private:
779 container_type payload;
780};
781
783template<typename Type, typename Entity, typename Allocator>
784class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<Type>::page_size == 0u>>
785 : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
786 using alloc_traits = std::allocator_traits<Allocator>;
787 static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
789
790public:
792 using allocator_type = Allocator;
796 using element_type = Type;
802 using size_type = std::size_t;
813
817
824
826 basic_storage(const basic_storage &) = delete;
827
832 basic_storage(basic_storage &&other) noexcept = default;
833
841
843 ~basic_storage() override = default;
844
850
857
863 // std::allocator<void> has no cross constructors (waiting for C++20)
864 if constexpr(std::is_void_v<element_type> && !std::is_constructible_v<allocator_type, typename base_type::allocator_type>) {
865 return allocator_type{};
866 } else {
868 }
869 }
870
880 void get([[maybe_unused]] const entity_type entt) const noexcept {
881 ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
882 }
883
889 [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
890 ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
891 return std::tuple{};
892 }
893
904 template<typename... Args>
905 void emplace(const entity_type entt, Args &&...) {
907 }
908
915 template<typename... Func>
916 void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
917 ENTT_ASSERT(base_type::contains(entt), "Invalid entity");
918 (std::forward<Func>(func)(), ...);
919 }
920
928 template<typename It, typename... Args>
929 void insert(It first, It last, Args &&...) {
930 for(; first != last; ++first) {
931 base_type::try_emplace(*first, true);
932 }
933 }
934
945
950
961
966};
967
973template<typename Entity, typename Allocator>
974class basic_storage<Entity, Entity, Allocator>
975 : public basic_sparse_set<Entity, Allocator> {
976 using alloc_traits = std::allocator_traits<Allocator>;
977 static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
978 using underlying_iterator = typename basic_sparse_set<Entity, Allocator>::basic_iterator;
980
981 auto next() noexcept {
983
984 do {
985 ENTT_ASSERT(placeholder < traits_type::to_entity(null), "No more entities available");
986 entt = traits_type::combine(static_cast<typename traits_type::entity_type>(placeholder++), {});
987 } while(base_type::current(entt) != traits_type::to_version(tombstone) && entt != null);
988
989 return entt;
990 }
991
992protected:
994 void pop_all() override {
996 placeholder = {};
997 }
998
1004 underlying_iterator try_emplace(const Entity hint, const bool, const void *) override {
1005 return base_type::find(emplace(hint));
1006 }
1007
1008public:
1010 using allocator_type = Allocator;
1020 using size_type = std::size_t;
1031
1036
1043
1045 basic_storage(const basic_storage &) = delete;
1046
1052 : base_type{std::move(other)},
1053 placeholder{other.placeholder} {}
1054
1061 : base_type{std::move(other), allocator},
1062 placeholder{other.placeholder} {}
1063
1065 ~basic_storage() override = default;
1066
1072
1079 placeholder = other.placeholder;
1080 base_type::operator=(std::move(other));
1081 return *this;
1082 }
1083
1093 void get([[maybe_unused]] const entity_type entt) const noexcept {
1094 ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
1095 }
1096
1102 [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
1103 ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
1104 return std::tuple{};
1105 }
1106
1112 const auto len = base_type::free_list();
1113 const auto entt = (len == base_type::size()) ? next() : base_type::data()[len];
1114 return *base_type::try_emplace(entt, true);
1115 }
1116
1127 if(hint != null && hint != tombstone) {
1128 if(const auto curr = traits_type::construct(traits_type::to_entity(hint), base_type::current(hint)); curr == tombstone || !(base_type::index(curr) < base_type::free_list())) {
1129 return *base_type::try_emplace(hint, true);
1130 }
1131 }
1132
1133 return emplace();
1134 }
1135
1142 template<typename... Func>
1143 void patch([[maybe_unused]] const entity_type entt, Func &&...func) {
1144 ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
1145 (std::forward<Func>(func)(), ...);
1146 }
1147
1154 template<typename It>
1155 void insert(It first, It last) {
1156 for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first) {
1158 }
1159
1160 for(; first != last; ++first) {
1161 *first = *base_type::try_emplace(next(), true);
1162 }
1163 }
1164
1173 return std::as_const(*this).each();
1174 }
1175
1178 const auto it = base_type::cend();
1180 }
1181
1190 return std::as_const(*this).reach();
1191 }
1192
1198
1199private:
1200 size_type placeholder{};
1201};
1202
1203} // namespace entt
1204
1205#endif
typename Traits::entity_type entity_type
Underlying entity type.
Definition entity.hpp:71
Sparse set implementation.
iterator begin() const noexcept
Returns an iterator to the beginning.
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
virtual basic_iterator try_emplace(const Entity entt, const bool force_back, const void *=nullptr)
Assigns an entity to a sparse set.
virtual void pop_all()
Erases all entities of a sparse set.
void swap_and_pop(const basic_iterator it)
Erases an entity from a sparse set.
iterator end() const noexcept
Returns an iterator to the end.
reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
pointer data() const noexcept
Direct access to the internal packed array.
virtual void reserve(const size_type cap)
Increases the capacity of a sparse set.
size_type size() const noexcept
Returns the number of elements in a sparse set.
basic_sparse_set & operator=(const basic_sparse_set &)=delete
Default copy assignment operator, deleted on purpose.
virtual void shrink_to_fit()
Requests the removal of unused capacity.
void swap(basic_sparse_set &other) noexcept
Exchanges the contents with those of a given sparse set.
const_iterator find(const entity_type entt) const noexcept
Finds an entity.
virtual void pop(basic_iterator first, basic_iterator last)
Erases entities from a sparse set.
version_type current(const entity_type entt) const noexcept
Returns the contained version for an identifier.
bool contains(const entity_type entt) const noexcept
Checks if a sparse set contains an entity.
const_iterator cend() const noexcept
Returns an iterator to the end.
void in_place_pop(const basic_iterator it)
Erases an entity from a sparse set.
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
constexpr allocator_type get_allocator() const noexcept
Returns the associated allocator.
const void * value(const entity_type entt) const noexcept
Returns the element assigned to an entity, if any.
reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
size_type free_list() const noexcept
Returns data on the free list whose meaning depends on the mode.
internal::sparse_set_iterator< packed_container_type > basic_iterator
Random access iterator type.
const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator to the beginning.
size_type index(const entity_type entt) const noexcept
Returns the position of an entity in a sparse set.
const_reverse_iterable reach() const noexcept
Returns a reverse iterable object to use to visit a storage.
Definition storage.hpp:1194
std::size_t size_type
Unsigned integer type.
Definition storage.hpp:1020
void get(const entity_type entt) const noexcept
Returns the object assigned to an entity, that is void.
Definition storage.hpp:1093
void value_type
Type of the objects assigned to entities.
Definition storage.hpp:1016
void insert(It first, It last)
Assigns each element in a range an identifier.
Definition storage.hpp:1155
Entity entity_type
Underlying entity identifier.
Definition storage.hpp:1018
void pop_all() override
Erases all entities of a storage.
Definition storage.hpp:994
entity_type emplace(const entity_type hint)
Creates a new identifier or recycles a destroyed one.
Definition storage.hpp:1126
~basic_storage() override=default
Default destructor.
underlying_iterator try_emplace(const Entity hint, const bool, const void *) override
Assigns an entity to a storage.
Definition storage.hpp:1004
basic_storage & operator=(basic_storage &&other) noexcept
Move assignment operator.
Definition storage.hpp:1078
reverse_iterable reach() noexcept
Returns a reverse iterable object to use to visit a storage.
Definition storage.hpp:1189
basic_storage(basic_storage &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition storage.hpp:1060
const_iterable each() const noexcept
Returns an iterable object to use to visit a storage.
Definition storage.hpp:1177
basic_storage(const allocator_type &allocator)
Constructs an empty container with a given allocator.
Definition storage.hpp:1041
basic_storage(basic_storage &&other) noexcept
Move constructor.
Definition storage.hpp:1051
entity_type emplace()
Creates a new identifier or recycles a destroyed one.
Definition storage.hpp:1111
iterable each() noexcept
Returns an iterable object to use to visit a storage.
Definition storage.hpp:1172
basic_storage(const basic_storage &)=delete
Default copy constructor, deleted on purpose.
void patch(const entity_type entt, Func &&...func)
Updates a given identifier.
Definition storage.hpp:1143
basic_storage & operator=(const basic_storage &)=delete
Default copy assignment operator, deleted on purpose.
std::tuple get_as_tuple(const entity_type entt) const noexcept
Returns an empty tuple.
Definition storage.hpp:1102
basic_storage(const basic_storage &)=delete
Default copy constructor, deleted on purpose.
void emplace(const entity_type entt, Args &&...)
Assigns an entity to a storage and constructs its object.
Definition storage.hpp:905
reverse_iterable reach() noexcept
Returns a reverse iterable object to use to visit a storage.
Definition storage.hpp:958
constexpr allocator_type get_allocator() const noexcept
Returns the associated allocator.
Definition storage.hpp:862
void get(const entity_type entt) const noexcept
Returns the object assigned to an entity, that is void.
Definition storage.hpp:880
basic_storage(const allocator_type &allocator)
Constructs an empty container with a given allocator.
Definition storage.hpp:822
basic_storage & operator=(const basic_storage &)=delete
Default copy assignment operator, deleted on purpose.
const_iterable each() const noexcept
Returns an iterable object to use to visit a storage.
Definition storage.hpp:947
void patch(const entity_type entt, Func &&...func)
Updates the instance assigned to a given entity in-place.
Definition storage.hpp:916
std::tuple get_as_tuple(const entity_type entt) const noexcept
Returns an empty tuple.
Definition storage.hpp:889
iterable each() noexcept
Returns an iterable object to use to visit a storage.
Definition storage.hpp:942
basic_storage & operator=(basic_storage &&other) noexcept=default
Move assignment operator.
basic_storage(basic_storage &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition storage.hpp:839
const_reverse_iterable reach() const noexcept
Returns a reverse iterable object to use to visit a storage.
Definition storage.hpp:963
Storage implementation.
Definition storage.hpp:230
iterator end() noexcept
Returns an iterator to the end.
Definition storage.hpp:585
internal::storage_iterator< const container_type > const_iterator
Constant random access iterator type.
Definition storage.hpp:412
~basic_storage() override
Default destructor.
Definition storage.hpp:465
basic_storage()
Default constructor.
Definition storage.hpp:429
iterator 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:737
const_reverse_iterator rbegin() const noexcept
Returns a reverse iterator to the beginning.
Definition storage.hpp:601
const_iterator end() const noexcept
Returns an iterator to the end.
Definition storage.hpp:580
const_pointer raw() const noexcept
Direct access to the array of objects.
Definition storage.hpp:538
void pop_all() override
Erases all entities of a storage.
Definition storage.hpp:353
basic_storage(basic_storage &&other) noexcept
Move constructor.
Definition storage.hpp:447
const value_type & get(const entity_type entt) const noexcept
Returns the object assigned to an entity.
Definition storage.hpp:639
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition storage.hpp:575
size_type capacity() const noexcept override
Returns the number of elements that a storage has currently allocated space for.
Definition storage.hpp:524
constexpr allocator_type get_allocator() const noexcept
Returns the associated allocator.
Definition storage.hpp:500
typename alloc_traits::template rebind_traits< typename alloc_traits::const_pointer >::const_pointer const_pointer
Constant pointer type to contained elements.
Definition storage.hpp:408
const_iterable each() const noexcept
Returns an iterable object to use to visit a storage.
Definition storage.hpp:758
void swap(basic_storage &other) noexcept
Exchanges the contents with those of a given storage.
Definition storage.hpp:490
element_type value_type
Type of the objects assigned to entities.
Definition storage.hpp:400
reverse_iterator rbegin() noexcept
Returns a reverse iterator to the beginning.
Definition storage.hpp:606
const_iterator begin() const noexcept
Returns an iterator to the beginning.
Definition storage.hpp:560
reverse_iterator rend() noexcept
Returns a reverse iterator to the end.
Definition storage.hpp:625
basic_storage & operator=(basic_storage &&other) noexcept
Move assignment operator.
Definition storage.hpp:480
Entity entity_type
Underlying entity identifier.
Definition storage.hpp:402
const_reverse_iterator rend() const noexcept
Returns a reverse iterator to the end.
Definition storage.hpp:620
underlying_iterator try_emplace(const Entity entt, const bool force_back, const void *value) override
Assigns an entity to a storage.
Definition storage.hpp:376
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition storage.hpp:554
std::reverse_iterator< const_iterator > const_reverse_iterator
Constant reverse iterator type.
Definition storage.hpp:416
value_type & patch(const entity_type entt, Func &&...func)
Updates the instance assigned to a given entity in-place.
Definition storage.hpp:693
std::reverse_iterator< iterator > reverse_iterator
Reverse iterator type.
Definition storage.hpp:414
std::size_t size_type
Unsigned integer type.
Definition storage.hpp:404
iterator 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:715
void pop(underlying_iterator first, underlying_iterator last) override
Erases entities from a storage.
Definition storage.hpp:334
typename container_type::pointer pointer
Pointer type to contained elements.
Definition storage.hpp:406
reverse_iterable reach() noexcept
Returns a reverse iterable object to use to visit a storage.
Definition storage.hpp:769
pointer raw() noexcept
Direct access to the array of objects.
Definition storage.hpp:543
std::tuple< value_type & > get_as_tuple(const entity_type entt) noexcept
Returns the object assigned to an entity as a tuple.
Definition storage.hpp:658
value_type & get(const entity_type entt) noexcept
Returns the object assigned to an entity.
Definition storage.hpp:644
const_reverse_iterator crend() const noexcept
Returns a reverse iterator to the end.
Definition storage.hpp:615
const_reverse_iterable reach() const noexcept
Returns a reverse iterable object to use to visit a storage.
Definition storage.hpp:774
iterable each() noexcept
Returns an iterable object to use to visit a storage.
Definition storage.hpp:753
basic_storage & operator=(const basic_storage &)=delete
Default copy assignment operator, deleted on purpose.
Type element_type
Element type.
Definition storage.hpp:398
void reserve(const size_type cap) override
Increases the capacity of a storage.
Definition storage.hpp:512
basic_storage(const allocator_type &allocator)
Constructs an empty storage with a given allocator.
Definition storage.hpp:436
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
Definition storage.hpp:675
std::tuple< const value_type & > get_as_tuple(const entity_type entt) const noexcept
Returns the object assigned to an entity as a tuple.
Definition storage.hpp:653
void shrink_to_fit() override
Requests the removal of unused capacity.
Definition storage.hpp:529
const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator to the beginning.
Definition storage.hpp:596
basic_storage(basic_storage &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition storage.hpp:456
basic_storage(const basic_storage &)=delete
Default copy constructor, deleted on purpose.
iterator begin() noexcept
Returns an iterator to the beginning.
Definition storage.hpp:565
internal::storage_iterator< container_type > iterator
Random access iterator type.
Definition storage.hpp:410
static constexpr deletion_policy storage_policy
Storage deletion policy.
Definition storage.hpp:426
Allocator allocator_type
Allocator type.
Definition storage.hpp:394
EnTT default namespace.
Definition dense_map.hpp:22
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition memory.hpp:219
constexpr std::enable_if_t< std::is_unsigned_v< Type >, Type > fast_mod(const Type value, const std::size_t mod) noexcept
Fast module utility function (powers of two only).
Definition bit.hpp:62
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:375
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
Definition entity.hpp:384
constexpr Type * uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition memory.hpp:238
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:168
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator<(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.
deletion_policy
Storage deletion policy.
Definition fwd.hpp:17
@ swap_only
Swap-only deletion policy.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
@ ref
Aliasing mode, the object points to a non-const element.
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
constexpr auto to_address(Type &&ptr) noexcept
Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
Definition memory.hpp:20
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Common way to access various properties of components.
Definition component.hpp:42
static constexpr std::size_t page_size
Page size, default is ENTT_PACKED_PAGE for non-empty types.
Definition component.hpp:51
static constexpr bool in_place_delete
Pointer stability, default is false.
Definition component.hpp:49
Entity traits.
Definition entity.hpp:163
Utility class to create an iterable object from a pair of iterators.
Definition iterator.hpp:141