From 4fb558f143ff127ae08941b017e2a930f987d559 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Mon, 12 Dec 2022 13:07:32 +0100 Subject: [PATCH] view: further reduce instantiations --- src/entt/entity/view.hpp | 64 ++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/entt/entity/view.hpp b/src/entt/entity/view.hpp index 1a492c34d..88565576e 100644 --- a/src/entt/entity/view.hpp +++ b/src/entt/entity/view.hpp @@ -23,6 +23,23 @@ namespace entt { namespace internal { +template +std::enable_if_t<(std::is_same_v && ...), const Type *> +pick_best(const Type *first, const Other *...other) noexcept { + ((first = other->size() < first->size() ? other : first), ...); + return first; +} + +template +auto filter_as_tuple(const std::array &filter) noexcept { + return std::apply([](const auto *...curr) { return std::make_tuple(static_cast(const_cast *>(curr))...); }, filter); +} + +template +[[nodiscard]] auto none_of(const std::array &filter, const typename Type::entity_type entt) noexcept { + return std::apply([entt](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter); +} + template class view_iterator final { using iterator_type = typename Type::const_iterator; @@ -30,7 +47,7 @@ class view_iterator final { [[nodiscard]] bool valid() const noexcept { return ((Get != 0u) || (*it != tombstone)) && std::apply([entt = *it](const auto *...curr) { return (curr->contains(entt) && ...); }, pools) - && std::apply([entt = *it](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter); + && none_of(filter, *it); } public: @@ -201,10 +218,6 @@ class basic_view, exclude_t> { return other; } - [[nodiscard]] auto filter_as_array() const noexcept { - return std::apply([](const auto *...curr) { return std::array{curr...}; }, filter); - } - template [[nodiscard]] auto dispatch_get(const std::tuple &curr) const { if constexpr(Curr == Other) { @@ -214,14 +227,10 @@ class basic_view, exclude_t> { } } - [[nodiscard]] auto reject(const underlying_type entt) const noexcept { - return std::apply([entt](const auto *...curr) { return (curr->contains(entt) || ...); }, filter); - } - template void each(Func &func, std::index_sequence) const { for(const auto curr: storage().each()) { - if(const auto entt = std::get<0>(curr); ((sizeof...(Get) != 1u) || (entt != tombstone)) && ((Curr == Index || storage().contains(entt)) && ...) && !reject(entt)) { + if(const auto entt = std::get<0>(curr); ((sizeof...(Get) != 1u) || (entt != tombstone)) && ((Curr == Index || storage().contains(entt)) && ...) && internal::none_of(filter, entt)) { if constexpr(is_applicable_v{}, std::declval().get({})))>) { std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get(curr)...)); } else { @@ -262,7 +271,7 @@ public: basic_view(Get &...value, Exclude &...exclude) noexcept : pools{&value...}, filter{&exclude...}, - view{[](const base_type *first, const auto *...other) { ((first = other->size() < first->size() ? other : first), ...); return first; }(&value...)} {} + view{internal::pick_best(static_cast(&value)...)} {} /** * @brief Constructs a multi-type view from a set of storage classes. @@ -270,9 +279,7 @@ public: * @param excl The storage for the types used to filter the view. */ basic_view(std::tuple value, std::tuple excl = {}) noexcept - : pools{std::apply([](auto &...curr) { return std::make_tuple(&curr...); }, value)}, - filter{std::apply([](auto &...curr) { return std::make_tuple(&curr...); }, excl)}, - view{std::apply([](const base_type *first, const auto *...other) { ((first = other->size() < first->size() ? other : first), ...); return first; }, pools)} {} + : basic_view{std::make_from_tuple(std::tuple_cat(value, excl))} {} /** * @brief Creates a new view driven by a given component in its iterations. @@ -301,7 +308,7 @@ public: * @return A newly created and internally optimized view. */ [[nodiscard]] basic_view refresh() const noexcept { - return std::apply([](auto *...elem) { return basic_view{*elem...}; }, std::tuple_cat(pools, filter)); + return std::apply([](auto *...elem) { return basic_view{*elem...}; }, std::tuple_cat(pools, internal::filter_as_tuple(filter))); } /** @@ -334,7 +341,7 @@ public: if constexpr(Index < offset) { return *std::get(pools); } else { - return *std::get(filter); + return *std::get(internal::filter_as_tuple(filter)); } } @@ -355,7 +362,7 @@ public: * @return An iterator to the first entity of the view. */ [[nodiscard]] iterator begin() const noexcept { - return iterator{view->begin(), view->end(), opaque_check_set(), filter_as_array()}; + return iterator{view->begin(), view->end(), opaque_check_set(), filter}; } /** @@ -368,7 +375,7 @@ public: * @return An iterator to the entity following the last entity of the view. */ [[nodiscard]] iterator end() const noexcept { - return iterator{view->end(), view->end(), opaque_check_set(), filter_as_array()}; + return iterator{view->end(), view->end(), opaque_check_set(), filter}; } /** @@ -399,7 +406,7 @@ public: * iterator otherwise. */ [[nodiscard]] iterator find(const entity_type entt) const noexcept { - return contains(entt) ? iterator{view->find(entt), view->end(), opaque_check_set(), filter_as_array()} : end(); + return contains(entt) ? iterator{view->find(entt), view->end(), opaque_check_set(), filter} : end(); } /** @@ -425,7 +432,7 @@ public: * @return True if the view contains the given entity, false otherwise. */ [[nodiscard]] bool contains(const entity_type entt) const noexcept { - return std::apply([entt](const auto *...curr) { return (curr->contains(entt) && ...); }, pools) && !reject(entt); + return std::apply([entt](const auto *...curr) { return (curr->contains(entt) && ...); }, pools) && internal::none_of(filter, entt); } /** @@ -516,13 +523,14 @@ public: */ template [[nodiscard]] auto operator|(const basic_view, exclude_t> &other) const noexcept { - return std::make_from_tuple, exclude_t>>( - std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, std::tuple_cat(pools, other.pools, filter, other.filter))); + return std::apply( + [](auto *...curr) { return basic_view, exclude_t>{*curr...}; }, + std::tuple_cat(pools, other.pools, internal::filter_as_tuple(filter), internal::filter_as_tuple(other.filter))); } private: std::tuple pools; - std::tuple filter; + std::array filter; const base_type *view; }; @@ -584,8 +592,7 @@ public: * @param ref The storage for the type to iterate. */ basic_view(std::tuple ref, std::tuple<> = {}) noexcept - : pools{&std::get<0>(ref)}, - filter{} {} + : basic_view{std::get<0>(ref)} {} /** * @brief Returns the leading storage of a view. @@ -835,13 +842,14 @@ public: */ template [[nodiscard]] auto operator|(const basic_view, exclude_t> &other) const noexcept { - return std::make_from_tuple, exclude_t>>( - std::apply([](auto *...curr) { return std::forward_as_tuple(*curr...); }, std::tuple_cat(pools, other.pools, other.filter))); + return std::apply( + [](auto *...curr) { return basic_view, exclude_t>{*curr...}; }, + std::tuple_cat(pools, other.pools, internal::filter_as_tuple(other.filter))); } private: std::tuple pools; - std::tuple<> filter; + std::array filter; }; /**