EnTT 3.14.0
Loading...
Searching...
No Matches
view.hpp
1#ifndef ENTT_ENTITY_VIEW_HPP
2#define ENTT_ENTITY_VIEW_HPP
3
4#include <array>
5#include <cstddef>
6#include <iterator>
7#include <tuple>
8#include <type_traits>
9#include <utility>
10#include "../config/config.h"
11#include "../core/iterator.hpp"
12#include "../core/type_traits.hpp"
13#include "entity.hpp"
14#include "fwd.hpp"
15
16namespace entt {
17
19namespace internal {
20
21template<typename Type>
22const Type *view_placeholder() {
23 static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
24 static const Type placeholder{};
25 return &placeholder;
26}
27
28template<typename It, typename Entity>
29[[nodiscard]] bool all_of(It first, const It last, const Entity entt) noexcept {
30 for(; (first != last) && (*first)->contains(entt); ++first) {}
31 return first == last;
32}
33
34template<typename It, typename Entity>
35[[nodiscard]] bool none_of(It first, const It last, const Entity entt) noexcept {
36 for(; (first != last) && !(*first)->contains(entt); ++first) {}
37 return first == last;
38}
39
40template<typename It>
41[[nodiscard]] bool fully_initialized(It first, const It last) noexcept {
42 for(const auto *placeholder = view_placeholder<std::remove_const_t<std::remove_pointer_t<typename std::iterator_traits<It>::value_type>>>(); (first != last) && *first != placeholder; ++first) {}
43 return first == last;
44}
45
46template<typename Result, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs>
47[[nodiscard]] Result view_pack(const View &view, const Other &other, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>) {
48 Result elem{};
49 // friend-initialization, avoid multiple calls to refresh
50 elem.pools = {view.template storage<GLhs>()..., other.template storage<GRhs>()...};
51 elem.filter = {view.template storage<sizeof...(GLhs) + ELhs>()..., other.template storage<sizeof...(GRhs) + ERhs>()...};
52 elem.refresh();
53 return elem;
54}
55
56template<typename Type, std::size_t Get, std::size_t Exclude>
57class view_iterator final {
58 template<typename, typename...>
59 friend class extended_view_iterator;
60
61 using iterator_type = typename Type::const_iterator;
62 using iterator_traits = std::iterator_traits<iterator_type>;
63
64 [[nodiscard]] bool valid(const typename iterator_traits::value_type entt) const noexcept {
65 return ((Get != 1u) || (entt != tombstone))
66 && internal::all_of(pools.begin(), pools.begin() + index, entt) && internal::all_of(pools.begin() + index + 1, pools.end(), entt)
67 && internal::none_of(filter.begin(), filter.end(), entt);
68 }
69
70 void seek_next() {
71 for(constexpr iterator_type sentinel{}; it != sentinel && !valid(*it); ++it) {}
72 }
73
74public:
75 using value_type = typename iterator_traits::value_type;
76 using pointer = typename iterator_traits::pointer;
77 using reference = typename iterator_traits::reference;
78 using difference_type = typename iterator_traits::difference_type;
79 using iterator_category = std::forward_iterator_tag;
80
81 constexpr view_iterator() noexcept
82 : it{},
83 pools{},
84 filter{},
85 index{} {}
86
87 view_iterator(iterator_type first, std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl, const std::size_t idx) noexcept
88 : it{first},
89 pools{value},
90 filter{excl},
91 index{idx} {
92 seek_next();
93 }
94
95 view_iterator &operator++() noexcept {
96 ++it;
97 seek_next();
98 return *this;
99 }
100
101 view_iterator operator++(int) noexcept {
102 view_iterator orig = *this;
103 return ++(*this), orig;
104 }
105
106 [[nodiscard]] pointer operator->() const noexcept {
107 return &*it;
108 }
109
110 [[nodiscard]] reference operator*() const noexcept {
111 return *operator->();
112 }
113
114 template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
115 friend constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &, const view_iterator<RhsType, RhsArgs...> &) noexcept;
116
117private:
118 iterator_type it;
119 std::array<const Type *, Get> pools;
120 std::array<const Type *, Exclude> filter;
121 std::size_t index;
122};
123
124template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
125[[nodiscard]] constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept {
126 return lhs.it == rhs.it;
127}
128
129template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs>
130[[nodiscard]] constexpr bool operator!=(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept {
131 return !(lhs == rhs);
132}
133
134template<typename It, typename... Get>
135class extended_view_iterator final {
136 template<std::size_t... Index>
137 [[nodiscard]] auto dereference(std::index_sequence<Index...>) const noexcept {
138 return std::tuple_cat(std::make_tuple(*it), static_cast<Get *>(const_cast<constness_as_t<typename Get::base_type, Get> *>(std::get<Index>(it.pools)))->get_as_tuple(*it)...);
139 }
140
141public:
142 using iterator_type = It;
143 using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Get>().get_as_tuple({})...));
144 using pointer = input_iterator_pointer<value_type>;
145 using reference = value_type;
146 using difference_type = std::ptrdiff_t;
147 using iterator_category = std::input_iterator_tag;
148 using iterator_concept = std::forward_iterator_tag;
149
150 constexpr extended_view_iterator()
151 : it{} {}
152
153 extended_view_iterator(iterator_type from)
154 : it{from} {}
155
156 extended_view_iterator &operator++() noexcept {
157 return ++it, *this;
158 }
159
160 extended_view_iterator operator++(int) noexcept {
161 extended_view_iterator orig = *this;
162 return ++(*this), orig;
163 }
164
165 [[nodiscard]] reference operator*() const noexcept {
166 return dereference(std::index_sequence_for<Get...>{});
167 }
168
169 [[nodiscard]] pointer operator->() const noexcept {
170 return operator*();
171 }
172
173 [[nodiscard]] constexpr iterator_type base() const noexcept {
174 return it;
175 }
176
177 template<typename... Lhs, typename... Rhs>
178 friend bool constexpr operator==(const extended_view_iterator<Lhs...> &, const extended_view_iterator<Rhs...> &) noexcept;
179
180private:
181 It it;
182};
183
184template<typename... Lhs, typename... Rhs>
185[[nodiscard]] constexpr bool operator==(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept {
186 return lhs.it == rhs.it;
187}
188
189template<typename... Lhs, typename... Rhs>
190[[nodiscard]] constexpr bool operator!=(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept {
191 return !(lhs == rhs);
192}
193
194} // namespace internal
215template<typename, typename, typename>
216class basic_view;
217
225template<typename Type, std::size_t Get, std::size_t Exclude>
227 static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
228
229 template<typename Return, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs>
230 friend Return internal::view_pack(const View &, const Other &, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>);
231
232 [[nodiscard]] auto offset() const noexcept {
233 ENTT_ASSERT(index != Get, "Invalid view");
234 return (pools[index]->policy() == deletion_policy::swap_only) ? pools[index]->free_list() : pools[index]->size();
235 }
236
237 void unchecked_refresh() noexcept {
238 index = 0u;
239
240 if constexpr(Get > 1u) {
241 for(size_type pos{1u}; pos < Get; ++pos) {
242 if(pools[pos]->size() < pools[index]->size()) {
243 index = pos;
244 }
245 }
246 }
247 }
248
249protected:
251 basic_common_view() noexcept {
252 for(size_type pos{}; pos < Exclude; ++pos) {
253 filter[pos] = internal::view_placeholder<Type>();
254 }
255 }
256
257 basic_common_view(std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl) noexcept
258 : pools{value},
259 filter{excl},
260 index{Get} {
261 unchecked_refresh();
262 }
263
264 [[nodiscard]] const Type *pool_at(const std::size_t pos) const noexcept {
265 return pools[pos];
266 }
267
268 [[nodiscard]] const Type *storage(const std::size_t pos) const noexcept {
269 if(pos < Get) {
270 return pools[pos];
271 }
272
273 if(const auto idx = pos - Get; filter[idx] != internal::view_placeholder<Type>()) {
274 return filter[idx];
275 }
276
277 return nullptr;
278 }
279
280 void storage(const std::size_t pos, const Type *elem) noexcept {
281 ENTT_ASSERT(elem != nullptr, "Unexpected element");
282
283 if(pos < Get) {
284 pools[pos] = elem;
285 refresh();
286 } else {
287 filter[pos - Get] = elem;
288 }
289 }
290
291 [[nodiscard]] bool none_of(const typename Type::entity_type entt) const noexcept {
292 return internal::none_of(filter.begin(), filter.end(), entt);
293 }
294
295 void use(const std::size_t pos) noexcept {
296 index = (index != Get) ? pos : Get;
297 }
300public:
302 using common_type = Type;
304 using entity_type = typename Type::entity_type;
306 using size_type = std::size_t;
308 using iterator = internal::view_iterator<common_type, Get, Exclude>;
309
312 size_type pos = static_cast<size_type>(index != Get) * Get;
313 for(; pos < Get && pools[pos] != nullptr; ++pos) {}
314
315 if(pos == Get) {
316 unchecked_refresh();
317 }
318 }
319
325 return (index != Get) ? pools[index] : nullptr;
326 }
327
333 return (index != Get) ? offset() : size_type{};
334 }
335
344 return (index != Get) ? iterator{pools[index]->end() - static_cast<typename iterator::difference_type>(offset()), pools, filter, index} : iterator{};
345 }
346
352 return (index != Get) ? iterator{pools[index]->end(), pools, filter, index} : iterator{};
353 }
354
361 const auto it = begin();
362 return it != end() ? *it : null;
363 }
364
371 if(index != Get) {
372 auto it = pools[index]->rbegin();
373 const auto last = it + static_cast<typename iterator::difference_type>(offset());
374 for(; it != last && !contains(*it); ++it) {}
375 return it == last ? null : *it;
376 }
377
378 return null;
379 }
380
387 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
388 return contains(entt) ? iterator{pools[index]->find(entt), pools, filter, index} : end();
389 }
390
395 [[nodiscard]] explicit operator bool() const noexcept {
396 return (index != Get) && internal::fully_initialized(filter.begin(), filter.end());
397 }
398
404 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
405 return (index != Get)
406 && internal::all_of(pools.begin(), pools.end(), entt)
407 && internal::none_of(filter.begin(), filter.end(), entt)
408 && pools[index]->index(entt) < offset();
409 }
410
411private:
412 std::array<const common_type *, Get> pools{};
413 std::array<const common_type *, Exclude> filter{};
414 size_type index{Get};
415};
416
429template<typename... Get, typename... Exclude>
430class basic_view<get_t<Get...>, exclude_t<Exclude...>, std::enable_if_t<(sizeof...(Get) != 0u)>>
431 : public basic_common_view<std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>, sizeof...(Get), sizeof...(Exclude)> {
432 using base_type = basic_common_view<std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>, sizeof...(Get), sizeof...(Exclude)>;
433
434 template<typename Type>
435 static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
436
437 template<std::size_t... Index>
438 [[nodiscard]] auto get(const typename base_type::entity_type entt, std::index_sequence<Index...>) const noexcept {
439 return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...);
440 }
441
442 template<std::size_t Curr, std::size_t Other, typename... Args>
443 [[nodiscard]] auto dispatch_get(const std::tuple<typename base_type::entity_type, Args...> &curr) const {
444 if constexpr(Curr == Other) {
445 return std::forward_as_tuple(std::get<Args>(curr)...);
446 } else {
447 return storage<Other>()->get_as_tuple(std::get<0>(curr));
448 }
449 }
450
451 template<std::size_t Curr, typename Func, std::size_t... Index>
452 void each(Func &func, std::index_sequence<Index...>) const {
453 static constexpr bool tombstone_check_required = ((sizeof...(Get) == 1u) && ... && (Get::storage_policy == deletion_policy::in_place));
454
455 for(const auto curr: storage<Curr>()->each()) {
456 if(const auto entt = std::get<0>(curr); (!tombstone_check_required || (entt != tombstone)) && ((Curr == Index || base_type::pool_at(Index)->contains(entt)) && ...) && base_type::none_of(entt)) {
457 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
458 std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Curr, Index>(curr)...));
459 } else {
460 std::apply(func, std::tuple_cat(dispatch_get<Curr, Index>(curr)...));
461 }
462 }
463 }
464 }
465
466 template<typename Func, std::size_t... Index>
467 void pick_and_each(Func &func, std::index_sequence<Index...> seq) const {
468 if(const auto *view = base_type::handle(); view != nullptr) {
469 ((view == base_type::pool_at(Index) ? each<Index>(func, seq) : void()), ...);
470 }
471 }
472
473public:
483 using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, Get...>>;
484
488
495 : base_type{{&value...}, {&excl...}} {
496 }
497
503 basic_view(std::tuple<Get &...> value, std::tuple<Exclude &...> excl = {}) noexcept
504 : basic_view{std::make_from_tuple<basic_view>(std::tuple_cat(value, excl))} {}
505
510 template<typename Type>
511 void use() noexcept {
513 }
514
519 template<std::size_t Index>
520 void use() noexcept {
521 base_type::use(Index);
522 }
523
529 template<typename Type>
531 return storage<index_of<Type>>();
532 }
533
539 template<std::size_t Index>
541 using type = type_list_element_t<Index, type_list<Get..., Exclude...>>;
542 return static_cast<type *>(const_cast<constness_as_t<common_type, type> *>(base_type::storage(Index)));
543 }
544
550 template<typename Type>
554
561 template<std::size_t Index, typename Type>
562 void storage(Type &elem) noexcept {
563 static_assert(std::is_convertible_v<Type &, type_list_element_t<Index, type_list<Get..., Exclude...>> &>, "Unexpected type");
564 base_type::storage(Index, &elem);
565 }
566
572 [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
573 return get(entt);
574 }
575
583 template<typename Type, typename... Other>
584 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
586 }
587
594 template<std::size_t... Index>
595 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
596 if constexpr(sizeof...(Index) == 0) {
597 return get(entt, std::index_sequence_for<Get...>{});
598 } else if constexpr(sizeof...(Index) == 1) {
599 return (storage<Index>()->get(entt), ...);
600 } else {
601 return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...);
602 }
603 }
604
620 template<typename Func>
621 void each(Func func) const {
622 pick_and_each(func, std::index_sequence_for<Get...>{});
623 }
624
635 return iterable{base_type::begin(), base_type::end()};
636 }
637
645 template<typename... OGet, typename... OExclude>
647 return internal::view_pack<basic_view<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>(
648 *this, other, std::index_sequence_for<Get...>{}, std::index_sequence_for<Exclude...>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
649 }
650};
651
658template<typename Type, deletion_policy Policy>
660 static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Unexpected type");
661
662protected:
664 basic_storage_view() noexcept = default;
665
666 basic_storage_view(const Type *value) noexcept
667 : leading{value} {
668 ENTT_ASSERT(leading->policy() == Policy, "Unexpected storage policy");
669 }
672public:
674 using common_type = Type;
676 using entity_type = typename common_type::entity_type;
678 using size_type = std::size_t;
680 using iterator = std::conditional_t<Policy == deletion_policy::in_place, internal::view_iterator<common_type, 1u, 0u>, typename common_type::iterator>;
682 using reverse_iterator = std::conditional_t<Policy == deletion_policy::in_place, void, typename common_type::reverse_iterator>;
683
689 return leading;
690 }
691
697 template<typename..., deletion_policy Pol = Policy>
698 [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, size_type> size() const noexcept {
699 if constexpr(Policy == deletion_policy::swap_and_pop) {
700 return leading ? leading->size() : size_type{};
701 } else {
702 static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
703 return leading ? leading->free_list() : size_type{};
704 }
705 }
706
712 template<typename..., deletion_policy Pol = Policy>
713 [[nodiscard]] std::enable_if_t<Pol == deletion_policy::in_place, size_type> size_hint() const noexcept {
714 return leading ? leading->size() : size_type{};
715 }
716
722 template<typename..., deletion_policy Pol = Policy>
723 [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, bool> empty() const noexcept {
724 if constexpr(Policy == deletion_policy::swap_and_pop) {
725 return !leading || leading->empty();
726 } else {
727 static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
728 return !leading || (leading->free_list() == 0u);
729 }
730 }
731
740 if constexpr(Policy == deletion_policy::swap_and_pop) {
741 return leading ? leading->begin() : iterator{};
742 } else if constexpr(Policy == deletion_policy::swap_only) {
743 return leading ? (leading->end() - leading->free_list()) : iterator{};
744 } else {
745 static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
746 return leading ? iterator{leading->begin(), {leading}, {}, 0u} : iterator{};
747 }
748 }
749
756 return leading ? leading->end() : iterator{};
757 } else {
758 static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
759 return leading ? iterator{leading->end(), {leading}, {}, 0u} : iterator{};
760 }
761 }
762
771 template<typename..., deletion_policy Pol = Policy>
772 [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rbegin() const noexcept {
773 return leading ? leading->rbegin() : reverse_iterator{};
774 }
775
783 template<typename..., deletion_policy Pol = Policy>
784 [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rend() const noexcept {
785 if constexpr(Policy == deletion_policy::swap_and_pop) {
786 return leading ? leading->rend() : reverse_iterator{};
787 } else {
788 static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
789 return leading ? (leading->rbegin() + leading->free_list()) : reverse_iterator{};
790 }
791 }
792
799 if constexpr(Policy == deletion_policy::swap_and_pop) {
800 return empty() ? null : *leading->begin();
801 } else if constexpr(Policy == deletion_policy::swap_only) {
802 return empty() ? null : *(leading->end() - leading->free_list());
803 } else {
804 static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
805 const auto it = begin();
806 return (it == end()) ? null : *it;
807 }
808 }
809
817 return empty() ? null : *leading->rbegin();
818 } else {
819 static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy");
820
821 if(leading) {
822 auto it = leading->rbegin();
823 const auto last = leading->rend();
824 for(; (it != last) && (*it == tombstone); ++it) {}
825 return it == last ? null : *it;
826 }
827
828 return null;
829 }
830 }
831
838 [[nodiscard]] iterator find(const entity_type entt) const noexcept {
839 if constexpr(Policy == deletion_policy::swap_and_pop) {
840 return leading ? leading->find(entt) : iterator{};
841 } else if constexpr(Policy == deletion_policy::swap_only) {
842 const auto it = leading ? leading->find(entt) : iterator{};
843 return leading && (static_cast<size_type>(it.index()) < leading->free_list()) ? it : iterator{};
844 } else {
845 const auto it = leading ? leading->find(entt) : typename common_type::iterator{};
846 return iterator{it, {leading}, {}, 0u};
847 }
848 }
849
854 [[nodiscard]] explicit operator bool() const noexcept {
855 return (leading != nullptr);
856 }
857
863 [[nodiscard]] bool contains(const entity_type entt) const noexcept {
865 return leading && leading->contains(entt);
866 } else {
867 static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy");
868 return leading && leading->contains(entt) && (leading->index(entt) < leading->free_list());
869 }
870 }
871
872private:
873 const common_type *leading{};
874};
875
886template<typename Get>
888 : public basic_storage_view<typename Get::base_type, Get::storage_policy> {
890
891public:
903 using iterable = std::conditional_t<Get::storage_policy == deletion_policy::in_place, iterable_adaptor<internal::extended_view_iterator<iterator, Get>>, decltype(std::declval<Get>().each())>;
904
908
914 : base_type{&value} {
915 }
916
921 basic_view(std::tuple<Get &> value, std::tuple<> = {}) noexcept
922 : basic_view{std::get<0>(value)} {}
923
929 template<typename Type = typename Get::element_type>
931 static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::element_type>, "Invalid element type");
932 return storage<0>();
933 }
934
940 template<std::size_t Index>
942 static_assert(Index == 0u, "Index out of bounds");
943 return static_cast<Get *>(const_cast<constness_as_t<common_type, Get> *>(base_type::handle()));
944 }
945
950 void storage(Get &elem) noexcept {
952 }
953
959 template<std::size_t Index>
960 void storage(Get &elem) noexcept {
961 static_assert(Index == 0u, "Index out of bounds");
962 *this = basic_view{elem};
963 }
964
970 return storage();
971 }
972
978 [[nodiscard]] decltype(auto) operator[](const entity_type entt) const {
979 return storage()->get(entt);
980 }
981
988 template<typename Elem>
989 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
990 static_assert(std::is_same_v<std::remove_const_t<Elem>, typename Get::element_type>, "Invalid element type");
991 return get<0>(entt);
992 }
993
1000 template<std::size_t... Index>
1001 [[nodiscard]] decltype(auto) get(const entity_type entt) const {
1002 if constexpr(sizeof...(Index) == 0) {
1003 return storage()->get_as_tuple(entt);
1004 } else {
1005 return storage<Index...>()->get(entt);
1006 }
1007 }
1008
1024 template<typename Func>
1025 void each(Func func) const {
1026 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
1027 for(const auto pack: each()) {
1028 std::apply(func, pack);
1029 }
1030 } else if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) {
1031 if constexpr(std::is_void_v<typename Get::value_type>) {
1032 for(size_type pos = base_type::size(); pos; --pos) {
1033 func();
1034 }
1035 } else {
1036 if(const auto len = base_type::size(); len != 0u) {
1037 for(auto last = storage()->end(), first = last - len; first != last; ++first) {
1038 func(*first);
1039 }
1040 }
1041 }
1042 } else {
1043 static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy");
1044
1045 for(const auto pack: each()) {
1046 std::apply([&func](const auto, auto &&...elem) { func(std::forward<decltype(elem)>(elem)...); }, pack);
1047 }
1048 }
1049 }
1050
1061 if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) {
1062 return base_type::handle() ? storage()->each() : iterable{};
1063 } else {
1064 static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy");
1065 return iterable{base_type::begin(), base_type::end()};
1066 }
1067 }
1068
1076 template<typename... OGet, typename... OExclude>
1078 return internal::view_pack<basic_view<get_t<Get, OGet...>, exclude_t<OExclude...>>>(
1079 *this, other, std::index_sequence_for<Get>{}, std::index_sequence_for<>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
1080 }
1081};
1082
1088template<typename... Type>
1090
1096template<typename... Get, typename... Exclude>
1097basic_view(std::tuple<Get &...>, std::tuple<Exclude &...> = {}) -> basic_view<get_t<Get...>, exclude_t<Exclude...>>;
1098
1099} // namespace entt
1100
1101#endif
Basic storage view implementation.
Definition view.hpp:226
size_type size_hint() const noexcept
Estimates the number of entities iterated by the view.
Definition view.hpp:332
void refresh() noexcept
Updates the internal leading view if required.
Definition view.hpp:311
Type common_type
Common type among all storage types.
Definition view.hpp:302
const common_type * handle() const noexcept
Returns the leading storage of a view, if any.
Definition view.hpp:324
bool contains(const entity_type entt) const noexcept
Checks if a view contains an entity.
Definition view.hpp:404
iterator begin() const noexcept
Returns an iterator to the first entity of the view.
Definition view.hpp:343
entity_type back() const noexcept
Returns the last entity of the view, if any.
Definition view.hpp:370
entity_type front() const noexcept
Returns the first entity of the view, if any.
Definition view.hpp:360
std::size_t size_type
Unsigned integer type.
Definition view.hpp:306
iterator end() const noexcept
Returns an iterator that is past the last entity of the view.
Definition view.hpp:351
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition view.hpp:387
internal::view_iterator< common_type, Get, Exclude > iterator
Forward iterator type.
Definition view.hpp:308
typename Type::entity_type entity_type
Underlying entity identifier.
Definition view.hpp:304
Basic storage view implementation.
Definition view.hpp:659
entity_type front() const noexcept
Returns the first entity of the view, if any.
Definition view.hpp:798
std::enable_if_t< Pol !=deletion_policy::in_place, bool > empty() const noexcept
Checks whether a view is empty.
Definition view.hpp:723
std::conditional_t< Policy==deletion_policy::in_place, void, typename common_type::reverse_iterator > reverse_iterator
Reverse iterator type.
Definition view.hpp:682
entity_type back() const noexcept
Returns the last entity of the view, if any.
Definition view.hpp:815
bool contains(const entity_type entt) const noexcept
Checks if a view contains an entity.
Definition view.hpp:863
std::enable_if_t< Pol !=deletion_policy::in_place, reverse_iterator > rend() const noexcept
Returns an iterator that is past the last entity of the reversed view.
Definition view.hpp:784
iterator end() const noexcept
Returns an iterator that is past the last entity of the view.
Definition view.hpp:754
std::conditional_t< Policy==deletion_policy::in_place, internal::view_iterator< common_type, 1u, 0u >, typename common_type::iterator > iterator
Random access iterator type.
Definition view.hpp:680
std::enable_if_t< Pol==deletion_policy::in_place, size_type > size_hint() const noexcept
Estimates the number of entities iterated by the view.
Definition view.hpp:713
std::enable_if_t< Pol !=deletion_policy::in_place, reverse_iterator > rbegin() const noexcept
Returns an iterator to the first entity of the reversed view.
Definition view.hpp:772
std::enable_if_t< Pol !=deletion_policy::in_place, size_type > size() const noexcept
Returns the number of entities that have the given element.
Definition view.hpp:698
std::size_t size_type
Unsigned integer type.
Definition view.hpp:678
typename common_type::entity_type entity_type
Underlying entity identifier.
Definition view.hpp:676
iterator begin() const noexcept
Returns an iterator to the first entity of the view.
Definition view.hpp:739
const common_type * handle() const noexcept
Returns the leading storage of a view, if any.
Definition view.hpp:688
Type common_type
Common type among all storage types.
Definition view.hpp:674
iterator find(const entity_type entt) const noexcept
Finds an entity.
Definition view.hpp:838
Storage implementation.
Definition storage.hpp:230
const value_type & get(const entity_type entt) const noexcept
Returns the object assigned to an entity.
Definition storage.hpp:639
basic_view(std::tuple< Get & > value, std::tuple<>={}) noexcept
Constructs a view from a storage class.
Definition view.hpp:921
typename base_type::entity_type entity_type
Underlying entity identifier.
Definition view.hpp:895
auto operator|(const basic_view< get_t< OGet... >, exclude_t< OExclude... > > &other) const noexcept
Combines two views in a more specific one.
Definition view.hpp:1077
basic_view(Get &value) noexcept
Constructs a view from a storage class.
Definition view.hpp:913
void storage(Get &elem) noexcept
Assigns a storage to a view.
Definition view.hpp:960
Get * operator->() const noexcept
Returns a pointer to the underlying storage.
Definition view.hpp:969
typename base_type::common_type common_type
Common type among all storage types.
Definition view.hpp:893
typename base_type::reverse_iterator reverse_iterator
Reverse iterator type.
Definition view.hpp:901
typename base_type::iterator iterator
Random access iterator type.
Definition view.hpp:899
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition view.hpp:930
basic_view() noexcept
Default constructor to use to create empty, invalid views.
Definition view.hpp:906
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition view.hpp:1025
iterable each() const noexcept
Returns an iterable object to use to visit a view.
Definition view.hpp:1060
void storage(Get &elem) noexcept
Assigns a storage to a view.
Definition view.hpp:950
typename base_type::size_type size_type
Unsigned integer type.
Definition view.hpp:897
std::conditional_t< Get::storage_policy==deletion_policy::in_place, iterable_adaptor< internal::extended_view_iterator< iterator, Get > >, decltype(std::declval< Get >().each())> iterable
Iterable view type.
Definition view.hpp:903
decltype(auto) get(const entity_type entt) const
Returns the element assigned to the given entity.
Definition view.hpp:989
typename base_type::common_type common_type
Common type among all storage types.
Definition view.hpp:475
basic_view() noexcept
Default constructor to use to create empty, invalid views.
Definition view.hpp:486
void each(Func func) const
Iterates entities and elements and applies the given function object to them.
Definition view.hpp:621
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition view.hpp:595
auto operator|(const basic_view< get_t< OGet... >, exclude_t< OExclude... > > &other) const noexcept
Combines two views in a more specific one.
Definition view.hpp:646
iterable each() const noexcept
Returns an iterable object to use to visit a view.
Definition view.hpp:634
decltype(auto) get(const entity_type entt) const
Returns the elements assigned to the given entity.
Definition view.hpp:584
void use() noexcept
Forces a view to use a given element to drive iterations.
Definition view.hpp:511
basic_view(std::tuple< Get &... > value, std::tuple< Exclude &... > excl={}) noexcept
Constructs a view from a set of storage classes.
Definition view.hpp:503
basic_view(Get &...value, Exclude &...excl) noexcept
Constructs a view from a set of storage classes.
Definition view.hpp:494
auto * storage() const noexcept
Returns the storage for a given element type, if any.
Definition view.hpp:530
View implementation.
Definition fwd.hpp:42
EnTT default namespace.
Definition dense_map.hpp:22
basic_view(Type &...storage) -> basic_view< get_t< Type... >, exclude_t<> >
Deduction guide.
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
Definition memory.hpp:219
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
constexpr null_t null
Compile-time constant for null entities.
Definition entity.hpp:375
basic_view< type_list_transform_t< Get, storage_for >, type_list_transform_t< Exclude, storage_for > > view
Alias declaration for the most common use case.
Definition fwd.hpp:278
constexpr bool is_applicable_v
Helper variable template.
constexpr tombstone_t tombstone
Compile-time constant for tombstone entities.
Definition entity.hpp:384
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:168
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
deletion_policy
Storage deletion policy.
Definition fwd.hpp:17
@ swap_only
Swap-only deletion policy.
@ swap_and_pop
Swap-and-pop deletion policy.
@ in_place
In-place 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.
basic_storage< Type > storage
Alias declaration for the most common use case.
Definition fwd.hpp:76
Alias for exclusion lists.
Definition fwd.hpp:141
Alias for lists of observed elements.
Definition fwd.hpp:158
Utility class to create an iterable object from a pair of iterators.
Definition iterator.hpp:141
A class to use to push around lists of types, nothing more.