Переглянути джерело

view: view_pack review to cleanup single type views

Michele Caini 2 роки тому
батько
коміт
642f4e70b5
1 змінених файлів з 42 додано та 46 видалено
  1. 42 46
      src/entt/entity/view.hpp

+ 42 - 46
src/entt/entity/view.hpp

@@ -47,11 +47,13 @@ template<typename Type>
     return pos == len;
 }
 
-template<typename... Get, typename... Exclude, std::size_t... Index>
-[[nodiscard]] auto view_pack(const std::tuple<Get *...> value, const std::tuple<Exclude *...> excl, std::index_sequence<Index...>) {
-    const auto pools = std::tuple_cat(value, excl);
-    basic_view<get_t<Get...>, exclude_t<Exclude...>> elem{};
-    (((std::get<Index>(pools) != nullptr) ? elem.template storage<Index>(*std::get<Index>(pools)) : void()), ...);
+template<typename Type, typename View, typename Other, std::size_t... VGet, std::size_t... VExclude, std::size_t... OGet, std::size_t... OExclude>
+[[nodiscard]] auto view_pack(const View &view, const Other &other, std::index_sequence<VGet...>, std::index_sequence<VExclude...>, std::index_sequence<OGet...>, std::index_sequence<OExclude...>) {
+    Type elem{};
+    // friend-initialization, avoid multiple calls to refresh
+    elem.pools = {view.storage<VGet>()..., other.storage<OGet>()...};
+    elem.filter = {view.storage<sizeof...(VGet) + VExclude>()..., other.storage<sizeof...(OGet) + OExclude>()...};
+    elem.refresh();
     return elem;
 }
 
@@ -222,8 +224,8 @@ class basic_view;
  */
 template<typename... Get, typename... Exclude>
 class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
-    template<typename, typename, typename>
-    friend class basic_view;
+    template<typename Type, typename View, typename Other, std::size_t... VGet, std::size_t... VExclude, std::size_t... OGet, std::size_t... OExclude>
+    friend auto internal::view_pack(const View &, const Other &, std::index_sequence<VGet...>, std::index_sequence<VExclude...>, std::index_sequence<OGet...>, std::index_sequence<OExclude...>);
 
     using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
     using underlying_type = typename base_type::entity_type;
@@ -553,10 +555,8 @@ public:
      */
     template<typename... OGet, typename... OExclude>
     [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
-        return internal::view_pack(
-            std::tuple_cat(pools, other.pools),
-            std::tuple_cat(internal::filter_as_tuple<Exclude...>(filter, std::index_sequence_for<Exclude...>{}), internal::filter_as_tuple<OExclude...>(other.filter, std::index_sequence_for<OExclude...>{})),
-            std::index_sequence_for<Get..., OGet..., Exclude..., OExclude...>{});
+        return internal::view_pack<basic_view<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>(
+            *this, other, std::index_sequence_for<Get...>{}, std::index_sequence_for<Exclude...>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
     }
 
 private:
@@ -577,9 +577,6 @@ private:
  */
 template<typename Get>
 class basic_view<get_t<Get>, exclude_t<>, std::void_t<std::enable_if_t<!Get::traits_type::in_place_delete>>> {
-    template<typename, typename, typename>
-    friend class basic_view;
-
 public:
     /*! @brief Common type among all storage types. */
     using common_type = typename Get::base_type;
@@ -596,16 +593,14 @@ public:
 
     /*! @brief Default constructor to use to create empty, invalid views. */
     basic_view() noexcept
-        : pools{},
-          filter{} {}
+        : view{} {}
 
     /**
      * @brief Constructs a view from a storage class.
      * @param value The storage for the type to iterate.
      */
     basic_view(Get &value) noexcept
-        : pools{&value},
-          filter{} {}
+        : view{&value} {}
 
     /**
      * @brief Constructs a view from a storage class.
@@ -630,7 +625,7 @@ public:
     template<typename Type = typename Get::value_type>
     [[nodiscard]] auto *storage() const noexcept {
         static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::value_type>, "Invalid component type");
-        return storage<0>();
+        return view;
     }
 
     /**
@@ -640,7 +635,8 @@ public:
      */
     template<std::size_t Index>
     [[nodiscard]] auto *storage() const noexcept {
-        return std::get<Index>(pools);
+        static_assert(Index == 0u, "Index out of bounds");
+        return view;
     }
 
     /**
@@ -648,7 +644,7 @@ public:
      * @param elem A storage to assign to the view.
      */
     void storage(Get &elem) noexcept {
-        storage<0>(elem);
+        view = &elem;
     }
 
     /**
@@ -658,7 +654,8 @@ public:
      */
     template<std::size_t Index>
     void storage(Get &elem) noexcept {
-        std::get<Index>(pools) = &elem;
+        static_assert(Index == 0u, "Index out of bounds");
+        view = &elem;
     }
 
     /**
@@ -666,7 +663,7 @@ public:
      * @return Number of entities that have the given component.
      */
     [[nodiscard]] size_type size() const noexcept {
-        return handle() ? handle()->size() : size_type{};
+        return view ? view->size() : size_type{};
     }
 
     /**
@@ -674,7 +671,7 @@ public:
      * @return True if the view is empty, false otherwise.
      */
     [[nodiscard]] bool empty() const noexcept {
-        return !handle() || handle()->empty();
+        return !view || view->empty();
     }
 
     /**
@@ -685,7 +682,7 @@ public:
      * @return An iterator to the first entity of the view.
      */
     [[nodiscard]] iterator begin() const noexcept {
-        return handle() ? handle()->begin() : iterator{};
+        return view ? view->common_type::begin() : iterator{};
     }
 
     /**
@@ -693,7 +690,7 @@ public:
      * @return An iterator to the entity following the last entity of the view.
      */
     [[nodiscard]] iterator end() const noexcept {
-        return handle() ? handle()->end() : iterator{};
+        return view ? view->common_type::end() : iterator{};
     }
 
     /**
@@ -704,7 +701,7 @@ public:
      * @return An iterator to the first entity of the reversed view.
      */
     [[nodiscard]] reverse_iterator rbegin() const noexcept {
-        return handle() ? handle()->rbegin() : reverse_iterator{};
+        return view ? view->common_type::rbegin() : reverse_iterator{};
     }
 
     /**
@@ -714,7 +711,7 @@ public:
      * reversed view.
      */
     [[nodiscard]] reverse_iterator rend() const noexcept {
-        return handle() ? handle()->rend() : reverse_iterator{};
+        return view ? view->common_type::rend() : reverse_iterator{};
     }
 
     /**
@@ -723,7 +720,7 @@ public:
      * otherwise.
      */
     [[nodiscard]] entity_type front() const noexcept {
-        return empty() ? null : *handle()->begin();
+        return empty() ? null : *view->common_type::begin();
     }
 
     /**
@@ -732,7 +729,7 @@ public:
      * otherwise.
      */
     [[nodiscard]] entity_type back() const noexcept {
-        return empty() ? null : *handle()->rbegin();
+        return empty() ? null : *view->common_type::rbegin();
     }
 
     /**
@@ -742,7 +739,7 @@ public:
      * iterator otherwise.
      */
     [[nodiscard]] iterator find(const entity_type entt) const noexcept {
-        return handle() ? handle()->find(entt) : iterator{};
+        return view ? view->find(entt) : iterator{};
     }
 
     /**
@@ -768,7 +765,7 @@ public:
      * @return True if the view is fully initialized, false otherwise.
      */
     [[nodiscard]] explicit operator bool() const noexcept {
-        return (handle() != nullptr);
+        return (view != nullptr);
     }
 
     /**
@@ -777,7 +774,7 @@ public:
      * @return True if the view contains the given entity, false otherwise.
      */
     [[nodiscard]] bool contains(const entity_type entt) const noexcept {
-        return handle() && handle()->contains(entt);
+        return view && view->contains(entt);
     }
 
     /**
@@ -824,16 +821,18 @@ public:
      */
     template<typename Func>
     void each(Func func) const {
-        if(auto *view = storage(); view) {
-            if constexpr(is_applicable_v<Func, decltype(*view->each().begin())>) {
+        if constexpr(is_applicable_v<Func, decltype(*view->each().begin())>) {
+            if(view) {
                 for(const auto pack: view->each()) {
                     std::apply(func, pack);
                 }
-            } else if constexpr(Get::traits_type::page_size == 0u) {
-                for(size_type pos{}, last = size(); pos < last; ++pos) {
-                    func();
-                }
-            } else {
+            }
+        } else if constexpr(Get::traits_type::page_size == 0u) {
+            for(size_type pos{}, last = size(); pos < last; ++pos) {
+                func();
+            }
+        } else {
+            if(view) {
                 for(auto &&component: *view) {
                     func(component);
                 }
@@ -863,15 +862,12 @@ public:
      */
     template<typename... OGet, typename... OExclude>
     [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept {
-        return internal::view_pack(
-            std::tuple_cat(pools, other.pools),
-            internal::filter_as_tuple<OExclude...>(other.filter, std::index_sequence_for<OExclude...>{}),
-            std::index_sequence_for<Get, OGet..., OExclude...>{});
+        return internal::view_pack<basic_view<get_t<Get, OGet...>, exclude_t<OExclude...>>>(
+            *this, other, std::index_sequence_for<Get>{}, std::index_sequence_for<>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{});
     }
 
 private:
-    std::tuple<Get *> pools;
-    std::array<const common_type *, 0u> filter;
+    Get *view;
 };
 
 /**