Просмотр исходного кода

view: further reduce instantiations

Michele Caini 3 лет назад
Родитель
Сommit
4fb558f143
1 измененных файлов с 36 добавлено и 28 удалено
  1. 36 28
      src/entt/entity/view.hpp

+ 36 - 28
src/entt/entity/view.hpp

@@ -23,6 +23,23 @@ namespace entt {
 
 namespace internal {
 
+template<typename Type, typename... Other>
+std::enable_if_t<(std::is_same_v<Type, Other> && ...), const Type *>
+pick_best(const Type *first, const Other *...other) noexcept {
+    ((first = other->size() < first->size() ? other : first), ...);
+    return first;
+}
+
+template<typename... Args, typename Type, std::size_t N>
+auto filter_as_tuple(const std::array<const Type *, N> &filter) noexcept {
+    return std::apply([](const auto *...curr) { return std::make_tuple(static_cast<Args *>(const_cast<constness_as_t<Type, Args> *>(curr))...); }, filter);
+}
+
+template<typename Type, std::size_t N>
+[[nodiscard]] auto none_of(const std::array<const Type *, N> &filter, const typename Type::entity_type entt) noexcept {
+    return std::apply([entt](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
+}
+
 template<typename Type, std::size_t Get, std::size_t Exclude>
 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<get_t<Get...>, exclude_t<Exclude...>> {
         return other;
     }
 
-    [[nodiscard]] auto filter_as_array() const noexcept {
-        return std::apply([](const auto *...curr) { return std::array<const base_type *, sizeof...(Exclude)>{curr...}; }, filter);
-    }
-
     template<std::size_t Curr, std::size_t Other, typename... Args>
     [[nodiscard]] auto dispatch_get(const std::tuple<underlying_type, Args...> &curr) const {
         if constexpr(Curr == Other) {
@@ -214,14 +227,10 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
         }
     }
 
-    [[nodiscard]] auto reject(const underlying_type entt) const noexcept {
-        return std::apply([entt](const auto *...curr) { return (curr->contains(entt) || ...); }, filter);
-    }
-
     template<std::size_t Curr, typename Func, std::size_t... Index>
     void each(Func &func, std::index_sequence<Index...>) const {
         for(const auto curr: storage<Curr>().each()) {
-            if(const auto entt = std::get<0>(curr); ((sizeof...(Get) != 1u) || (entt != tombstone)) && ((Curr == Index || storage<Index>().contains(entt)) && ...) && !reject(entt)) {
+            if(const auto entt = std::get<0>(curr); ((sizeof...(Get) != 1u) || (entt != tombstone)) && ((Curr == Index || storage<Index>().contains(entt)) && ...) && internal::none_of(filter, entt)) {
                 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {
                     std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Curr, Index>(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<const base_type *>(&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<Get &...> value, std::tuple<Exclude &...> 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<basic_view>(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<Exclude...>(filter)));
     }
 
     /**
@@ -334,7 +341,7 @@ public:
         if constexpr(Index < offset) {
             return *std::get<Index>(pools);
         } else {
-            return *std::get<Index - offset>(filter);
+            return *std::get<Index - offset>(internal::filter_as_tuple<Exclude...>(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<typename... OGet, typename... OExclude>
     [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
-        return std::make_from_tuple<basic_view<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>(
-            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<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>{*curr...}; },
+            std::tuple_cat(pools, other.pools, internal::filter_as_tuple<Exclude...>(filter), internal::filter_as_tuple<OExclude...>(other.filter)));
     }
 
 private:
     std::tuple<Get *...> pools;
-    std::tuple<Exclude *...> filter;
+    std::array<const base_type *, sizeof...(Exclude)> filter;
     const base_type *view;
 };
 
@@ -584,8 +592,7 @@ public:
      * @param ref The storage for the type to iterate.
      */
     basic_view(std::tuple<Get &> 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<typename... OGet, typename... OExclude>
     [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
-        return std::make_from_tuple<basic_view<get_t<Get, OGet...>, exclude_t<OExclude...>>>(
-            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<get_t<Get, OGet...>, exclude_t<OExclude...>>{*curr...}; },
+            std::tuple_cat(pools, other.pools, internal::filter_as_tuple<OExclude...>(other.filter)));
     }
 
 private:
     std::tuple<Get *> pools;
-    std::tuple<> filter;
+    std::array<const base_type *, 0u> filter;
 };
 
 /**