@@ -23,14 +23,31 @@ namespace entt {
2323
2424namespace internal {
2525
26+ template <typename Type, typename ... Other>
27+ std::enable_if_t <(std::is_same_v<Type, Other> && ...), const Type *>
28+ pick_best (const Type *first, const Other *...other) noexcept {
29+ ((first = other->size () < first->size () ? other : first), ...);
30+ return first;
31+ }
32+
33+ template <typename ... Args, typename Type, std::size_t N>
34+ auto filter_as_tuple (const std::array<const Type *, N> &filter) noexcept {
35+ return std::apply ([](const auto *...curr ) { return std::make_tuple (static_cast <Args *>(const_cast <constness_as_t <Type, Args> *>(curr))...); }, filter);
36+ }
37+
38+ template <typename Type, std::size_t N>
39+ [[nodiscard]] auto none_of (const std::array<const Type *, N> &filter, const typename Type::entity_type entt) noexcept {
40+ return std::apply ([entt](const auto *...curr ) { return (!curr->contains (entt) && ...); }, filter);
41+ }
42+
2643template <typename Type, std::size_t Get, std::size_t Exclude>
2744class view_iterator final {
2845 using iterator_type = typename Type::const_iterator;
2946
3047 [[nodiscard]] bool valid () const noexcept {
3148 return ((Get != 0u ) || (*it != tombstone))
3249 && std::apply ([entt = *it](const auto *...curr ) { return (curr->contains (entt) && ...); }, pools)
33- && std::apply ([entt = *it]( const auto *... curr ) { return (!curr-> contains (entt) && ...); }, filter );
50+ && none_of (filter, *it);
3451 }
3552
3653public:
@@ -201,10 +218,6 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
201218 return other;
202219 }
203220
204- [[nodiscard]] auto filter_as_array () const noexcept {
205- return std::apply ([](const auto *...curr ) { return std::array<const base_type *, sizeof ...(Exclude)>{curr...}; }, filter);
206- }
207-
208221 template <std::size_t Curr, std::size_t Other, typename ... Args>
209222 [[nodiscard]] auto dispatch_get (const std::tuple<underlying_type, Args...> &curr) const {
210223 if constexpr (Curr == Other) {
@@ -214,14 +227,10 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
214227 }
215228 }
216229
217- [[nodiscard]] auto reject (const underlying_type entt) const noexcept {
218- return std::apply ([entt](const auto *...curr ) { return (curr->contains (entt) || ...); }, filter);
219- }
220-
221230 template <std::size_t Curr, typename Func, std::size_t ... Index>
222231 void each (Func &func, std::index_sequence<Index...>) const {
223232 for (const auto curr: storage<Curr>().each ()) {
224- if (const auto entt = std::get<0 >(curr); ((sizeof ...(Get) != 1u ) || (entt != tombstone)) && ((Curr == Index || storage<Index>().contains (entt)) && ...) && ! reject ( entt)) {
233+ if (const auto entt = std::get<0 >(curr); ((sizeof ...(Get) != 1u ) || (entt != tombstone)) && ((Curr == Index || storage<Index>().contains (entt)) && ...) && internal::none_of (filter, entt)) {
225234 if constexpr (is_applicable_v<Func, decltype (std::tuple_cat (std::tuple<entity_type>{}, std::declval<basic_view>().get ({})))>) {
226235 std::apply (func, std::tuple_cat (std::make_tuple (entt), dispatch_get<Curr, Index>(curr)...));
227236 } else {
@@ -262,17 +271,15 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
262271 basic_view (Get &...value, Exclude &...exclude) noexcept
263272 : pools{&value...},
264273 filter{&exclude...},
265- view{[]( const base_type *first, const auto *... other ) { ((first = other-> size () < first-> size () ? other : first), ...); return first; }( &value...)} {}
274+ view{internal::pick_best ( static_cast < const base_type *>( &value) ...)} {}
266275
267276 /* *
268277 * @brief Constructs a multi-type view from a set of storage classes.
269278 * @param value The storage for the types to iterate.
270279 * @param excl The storage for the types used to filter the view.
271280 */
272281 basic_view (std::tuple<Get &...> value, std::tuple<Exclude &...> excl = {}) noexcept
273- : pools{std::apply ([](auto &...curr ) { return std::make_tuple (&curr...); }, value)},
274- filter{std::apply ([](auto &...curr ) { return std::make_tuple (&curr...); }, excl)},
275- view{std::apply ([](const base_type *first, const auto *...other ) { ((first = other->size () < first->size () ? other : first), ...); return first; }, pools)} {}
282+ : basic_view{std::make_from_tuple<basic_view>(std::tuple_cat (value, excl))} {}
276283
277284 /* *
278285 * @brief Creates a new view driven by a given component in its iterations.
@@ -301,7 +308,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
301308 * @return A newly created and internally optimized view.
302309 */
303310 [[nodiscard]] basic_view refresh () const noexcept {
304- return std::apply ([](auto *...elem ) { return basic_view{*elem...}; }, std::tuple_cat (pools, filter));
311+ return std::apply ([](auto *...elem ) { return basic_view{*elem...}; }, std::tuple_cat (pools, internal::filter_as_tuple<Exclude...>( filter) ));
305312 }
306313
307314 /* *
@@ -334,7 +341,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
334341 if constexpr (Index < offset) {
335342 return *std::get<Index>(pools);
336343 } else {
337- return *std::get<Index - offset>(filter);
344+ return *std::get<Index - offset>(internal::filter_as_tuple<Exclude...>( filter) );
338345 }
339346 }
340347
@@ -355,7 +362,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
355362 * @return An iterator to the first entity of the view.
356363 */
357364 [[nodiscard]] iterator begin () const noexcept {
358- return iterator{view->begin (), view->end (), opaque_check_set (), filter_as_array () };
365+ return iterator{view->begin (), view->end (), opaque_check_set (), filter };
359366 }
360367
361368 /* *
@@ -368,7 +375,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
368375 * @return An iterator to the entity following the last entity of the view.
369376 */
370377 [[nodiscard]] iterator end () const noexcept {
371- return iterator{view->end (), view->end (), opaque_check_set (), filter_as_array () };
378+ return iterator{view->end (), view->end (), opaque_check_set (), filter };
372379 }
373380
374381 /* *
@@ -399,7 +406,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
399406 * iterator otherwise.
400407 */
401408 [[nodiscard]] iterator find (const entity_type entt) const noexcept {
402- return contains (entt) ? iterator{view->find (entt), view->end (), opaque_check_set (), filter_as_array () } : end ();
409+ return contains (entt) ? iterator{view->find (entt), view->end (), opaque_check_set (), filter } : end ();
403410 }
404411
405412 /* *
@@ -425,7 +432,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
425432 * @return True if the view contains the given entity, false otherwise.
426433 */
427434 [[nodiscard]] bool contains (const entity_type entt) const noexcept {
428- return std::apply ([entt](const auto *...curr ) { return (curr->contains (entt) && ...); }, pools) && ! reject ( entt);
435+ return std::apply ([entt](const auto *...curr ) { return (curr->contains (entt) && ...); }, pools) && internal::none_of (filter, entt);
429436 }
430437
431438 /* *
@@ -516,13 +523,14 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
516523 */
517524 template <typename ... OGet, typename ... OExclude>
518525 [[nodiscard]] auto operator |(const basic_view<get_t <OGet...>, exclude_t <OExclude...>> &other) const noexcept {
519- return std::make_from_tuple<basic_view<get_t <Get..., OGet...>, exclude_t <Exclude..., OExclude...>>>(
520- std::apply ([](auto *...curr ) { return std::forward_as_tuple (*curr...); }, std::tuple_cat (pools, other.pools , filter, other.filter )));
526+ return std::apply (
527+ [](auto *...curr ) { return basic_view<get_t <Get..., OGet...>, exclude_t <Exclude..., OExclude...>>{*curr...}; },
528+ std::tuple_cat (pools, other.pools , internal::filter_as_tuple<Exclude...>(filter), internal::filter_as_tuple<OExclude...>(other.filter )));
521529 }
522530
523531private:
524532 std::tuple<Get *...> pools;
525- std::tuple<Exclude * ...> filter;
533+ std::array< const base_type *, sizeof ...(Exclude) > filter;
526534 const base_type *view;
527535};
528536
@@ -584,8 +592,7 @@ class basic_view<get_t<Get>, exclude_t<>, std::void_t<std::enable_if_t<!Get::tra
584592 * @param ref The storage for the type to iterate.
585593 */
586594 basic_view (std::tuple<Get &> ref, std::tuple<> = {}) noexcept
587- : pools{&std::get<0 >(ref)},
588- filter{} {}
595+ : basic_view{std::get<0 >(ref)} {}
589596
590597 /* *
591598 * @brief Returns the leading storage of a view.
@@ -835,13 +842,14 @@ class basic_view<get_t<Get>, exclude_t<>, std::void_t<std::enable_if_t<!Get::tra
835842 */
836843 template <typename ... OGet, typename ... OExclude>
837844 [[nodiscard]] auto operator |(const basic_view<get_t <OGet...>, exclude_t <OExclude...>> &other) const noexcept {
838- return std::make_from_tuple<basic_view<get_t <Get, OGet...>, exclude_t <OExclude...>>>(
839- std::apply ([](auto *...curr ) { return std::forward_as_tuple (*curr...); }, std::tuple_cat (pools, other.pools , other.filter )));
845+ return std::apply (
846+ [](auto *...curr ) { return basic_view<get_t <Get, OGet...>, exclude_t <OExclude...>>{*curr...}; },
847+ std::tuple_cat (pools, other.pools , internal::filter_as_tuple<OExclude...>(other.filter )));
840848 }
841849
842850private:
843851 std::tuple<Get *> pools;
844- std::tuple< > filter;
852+ std::array< const base_type *, 0u > filter;
845853};
846854
847855/* *
0 commit comments