Skip to content

Commit 4fb558f

Browse files
committed
view: further reduce instantiations
1 parent 5762a8a commit 4fb558f

File tree

1 file changed

+36
-28
lines changed

1 file changed

+36
-28
lines changed

src/entt/entity/view.hpp

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,31 @@ namespace entt {
2323

2424
namespace 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+
2643
template<typename Type, std::size_t Get, std::size_t Exclude>
2744
class 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

3653
public:
@@ -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

523531
private:
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

842850
private:
843851
std::tuple<Get *> pools;
844-
std::tuple<> filter;
852+
std::array<const base_type *, 0u> filter;
845853
};
846854

847855
/**

0 commit comments

Comments
 (0)