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

entity/*:
* add owned_t utility
* change view def to basic_view<T, get_t<C...>, exclude_t<E...>>
* change group def to basic_group<T, owned_t<O...>, get_t<G...>, exclude_t<E...>>
* remove view dispatcher (reduce instantiations)
* make basic_view::traverse use the local policy

Michele Caini 4 лет назад
Родитель
Сommit
c52b2a4fa9

+ 0 - 1
TODO

@@ -5,7 +5,6 @@
 * custom pools example (multi instance, tables, enable/disable, and so on...)
 
 WIP:
-* remove view dispatcher, add support to relax policy constraints on user request (eg view.use<T>())
 * custom allocators all over
 
 WIP:

+ 8 - 6
src/entt/entity/fwd.hpp

@@ -4,6 +4,7 @@
 
 #include <memory>
 #include "../core/fwd.hpp"
+#include "utility.hpp"
 
 
 namespace entt {
@@ -21,15 +22,15 @@ template<typename>
 class basic_registry;
 
 
-template<typename...>
-struct basic_view;
+template<typename, typename, typename, typename = void>
+class basic_view;
 
 
 template<typename>
 class basic_runtime_view;
 
 
-template<typename...>
+template<typename, typename, typename, typename>
 class basic_group;
 
 
@@ -123,10 +124,11 @@ using continuous_loader = basic_continuous_loader<entity>;
 
 /**
  * @brief Alias declaration for the most common use case.
- * @tparam Args Other template parameters.
+ * @tparam Get Types of components iterated by the view.
+ * @tparam Exclude Types of components used to filter the view.
  */
-template<typename... Args>
-using view = basic_view<entity, Args...>;
+template<typename Get, typename Exclude = exclude_t<>>
+using view = basic_view<entity, Get, Exclude>;
 
 
 /*! @brief Alias declaration for the most common use case. */

+ 8 - 8
src/entt/entity/group.hpp

@@ -23,7 +23,7 @@ namespace entt {
  * Primary template isn't defined on purpose. All the specializations give a
  * compile-time error, but for a few reasonable cases.
  */
-template<typename...>
+template<typename, typename, typename, typename>
 class basic_group;
 
 
@@ -60,11 +60,11 @@ class basic_group;
  * In any other case, attempting to use a group results in undefined behavior.
  *
  * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the group.
  * @tparam Get Type of components observed by the group.
+ * @tparam Exclude Types of components used to filter the group.
  */
-template<typename Entity, typename... Exclude, typename... Get>
-class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>> final {
+template<typename Entity, typename... Get, typename... Exclude>
+class basic_group<Entity, owned_t<>, get_t<Get...>, exclude_t<Exclude...>> final {
     /*! @brief A registry is allowed to create groups. */
     friend class basic_registry<Entity>;
 
@@ -524,12 +524,12 @@ private:
  * In any other case, attempting to use a group results in undefined behavior.
  *
  * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the group.
- * @tparam Get Types of components observed by the group.
  * @tparam Owned Types of components owned by the group.
+ * @tparam Get Types of components observed by the group.
+ * @tparam Exclude Types of components used to filter the group.
  */
-template<typename Entity, typename... Exclude, typename... Get, typename... Owned>
-class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> final {
+template<typename Entity, typename... Owned, typename... Get, typename... Exclude>
+class basic_group<Entity, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> final {
     /*! @brief A registry is allowed to create groups. */
     friend class basic_registry<Entity>;
 

+ 4 - 4
src/entt/entity/helper.hpp

@@ -38,7 +38,7 @@ struct as_view {
      * @return A newly created view.
      */
     template<typename Exclude, typename... Component>
-    operator basic_view<entity_type, Exclude, Component...>() const {
+    operator basic_view<entity_type, get_t<Component...>, Exclude>() const {
         return reg.template view<Component...>(Exclude{});
     }
 
@@ -82,13 +82,13 @@ struct as_group {
 
     /**
      * @brief Conversion function from a registry to a group.
-     * @tparam Exclude Types of components used to filter the group.
      * @tparam Get Types of components observed by the group.
+     * @tparam Exclude Types of components used to filter the group.
      * @tparam Owned Types of components owned by the group.
      * @return A newly created group.
      */
-    template<typename Exclude, typename Get, typename... Owned>
-    operator basic_group<entity_type, Exclude, Get, Owned...>() const {
+    template<typename Get, typename Exclude, typename... Owned>
+    operator basic_group<entity_type, owned_t<Owned...>, Get, Exclude>() const {
         if constexpr(std::is_const_v<registry_type>) {
             return reg.template group_if_exists<Owned...>(Get{}, Exclude{});
         } else {

+ 7 - 7
src/entt/entity/organizer.hpp

@@ -29,8 +29,8 @@ namespace internal {
 template<typename>
 struct is_view: std::false_type {};
 
-template<typename Entity, typename... Exclude, typename... Component>
-struct is_view<basic_view<Entity, exclude_t<Exclude...>, Component...>>: std::true_type {};
+template<typename Entity, typename... Component, typename... Exclude>
+struct is_view<basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>>: std::true_type {};
 
 template<typename Type>
 inline constexpr bool is_view_v = is_view<Type>::value;
@@ -62,15 +62,15 @@ struct unpack_type<const basic_registry<Entity>, type_list<Override...>>
     : unpack_type<basic_registry<Entity>, type_list<Override...>>
 {};
 
-template<typename Entity, typename... Exclude, typename... Component, typename... Override>
-struct unpack_type<basic_view<Entity, exclude_t<Exclude...>, Component...>, type_list<Override...>> {
+template<typename Entity, typename... Component, typename... Exclude, typename... Override>
+struct unpack_type<basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>, type_list<Override...>> {
     using ro = type_list_cat_t<type_list<Exclude...>, typename unpack_type<Component, type_list<Override...>>::ro...>;
     using rw = type_list_cat_t<typename unpack_type<Component, type_list<Override...>>::rw...>;
 };
 
-template<typename Entity, typename... Exclude, typename... Component, typename... Override>
-struct unpack_type<const basic_view<Entity, exclude_t<Exclude...>, Component...>, type_list<Override...>>
-    : unpack_type<basic_view<Entity, exclude_t<Exclude...>, Component...>, type_list<Override...>>
+template<typename Entity, typename... Component, typename... Exclude, typename... Override>
+struct unpack_type<const basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>, type_list<Override...>>
+    : unpack_type<basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>>, type_list<Override...>>
 {};
 
 

+ 7 - 7
src/entt/entity/registry.hpp

@@ -1143,14 +1143,14 @@ public:
      * @return A newly created view.
      */
     template<typename... Component, typename... Exclude>
-    [[nodiscard]] basic_view<Entity, exclude_t<Exclude...>, std::add_const_t<Component>...> view(exclude_t<Exclude...> = {}) const {
+    [[nodiscard]] basic_view<Entity, get_t<std::add_const_t<Component>...>, exclude_t<Exclude...>> view(exclude_t<Exclude...> = {}) const {
         static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
         return { *assure<std::remove_const_t<Component>>()..., *assure<Exclude>()... };
     }
 
     /*! @copydoc view */
     template<typename... Component, typename... Exclude>
-    [[nodiscard]] basic_view<Entity, exclude_t<Exclude...>, Component...> view(exclude_t<Exclude...> = {}) {
+    [[nodiscard]] basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> view(exclude_t<Exclude...> = {}) {
         static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported");
         return { *assure<std::remove_const_t<Component>>()..., *assure<Exclude>()... };
     }
@@ -1229,7 +1229,7 @@ public:
      * @return A newly created group.
      */
     template<typename... Owned, typename... Get, typename... Exclude>
-    [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> group(get_t<Get...>, exclude_t<Exclude...> = {}) {
+    [[nodiscard]] basic_group<Entity, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> group(get_t<Get...>, exclude_t<Exclude...> = {}) {
         static_assert(sizeof...(Owned) + sizeof...(Get) > 0, "Exclusion-only groups are not supported");
         static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1, "Single component groups are not allowed");
 
@@ -1319,7 +1319,7 @@ public:
      * @return A newly created group.
      */
     template<typename... Owned, typename... Get, typename... Exclude>
-    [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<std::add_const_t<Get>...>, std::add_const_t<Owned>...> group_if_exists(get_t<Get...>, exclude_t<Exclude...> = {}) const {
+    [[nodiscard]] basic_group<Entity, owned_t<std::add_const_t<Owned>...>, get_t<std::add_const_t<Get>...>, exclude_t<Exclude...>> group_if_exists(get_t<Get...>, exclude_t<Exclude...> = {}) const {
         if(auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) {
             return gdata.size == (sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude))
                 && (gdata.owned(type_hash<std::remove_const_t<Owned>>::value()) && ...)
@@ -1344,7 +1344,7 @@ public:
      * @return A newly created group.
      */
     template<typename... Owned, typename... Exclude>
-    [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<>, Owned...> group(exclude_t<Exclude...> = {}) {
+    [[nodiscard]] basic_group<Entity, owned_t<Owned...>, get_t<>, exclude_t<Exclude...>> group(exclude_t<Exclude...> = {}) {
         return group<Owned...>(get_t<>{}, exclude<Exclude...>);
     }
 
@@ -1358,7 +1358,7 @@ public:
      * @return A newly created group.
      */
     template<typename... Owned, typename... Exclude>
-    [[nodiscard]] basic_group<Entity, exclude_t<Exclude...>, get_t<>, std::add_const_t<Owned>...> group_if_exists(exclude_t<Exclude...> = {}) const {
+    [[nodiscard]] basic_group<Entity, owned_t<std::add_const_t<Owned>...>, get_t<>, exclude_t<Exclude...>> group_if_exists(exclude_t<Exclude...> = {}) const {
         return group_if_exists<std::add_const_t<Owned>...>(get_t<>{}, exclude<Exclude...>);
     }
 
@@ -1381,7 +1381,7 @@ public:
      * @return True if the group can be sorted, false otherwise.
      */
     template<typename... Owned, typename... Get, typename... Exclude>
-    [[nodiscard]] bool sortable(const basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> &) ENTT_NOEXCEPT {
+    [[nodiscard]] bool sortable(const basic_group<Entity, owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> &) ENTT_NOEXCEPT {
         constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
         return std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
             return (0u + ... + gdata.owned(type_hash<std::remove_const_t<Owned>>::value())) && (size < gdata.size);

+ 16 - 0
src/entt/entity/utility.hpp

@@ -40,6 +40,22 @@ template<typename... Type>
 inline constexpr get_t<Type...> get{};
 
 
+/**
+ * @brief Alias for lists of owned components.
+ * @tparam Type List of types.
+ */
+template<typename... Type>
+struct owned_t: type_list<Type...>{};
+
+
+/**
+ * @brief Variable template for lists of owned components.
+ * @tparam Type List of types.
+ */
+template<typename... Type>
+inline constexpr owned_t<Type...> owned{};
+
+
 }
 
 

+ 52 - 73
src/entt/entity/view.hpp

@@ -110,7 +110,7 @@ private:
 };
 
 
-template<typename Policy, typename Type, typename It, std::size_t Component, std::size_t Exclude>
+template<typename Type, typename It, std::size_t Component, std::size_t Exclude, typename Policy>
 class view_iterator final {
     [[nodiscard]] bool valid() const {
         const auto entt = *it;
@@ -193,7 +193,7 @@ private:
 
 
 template<bool Enable>
-struct stable_iteration {
+struct policy_dispatcher {
     template<typename Entity>
     [[nodiscard]] static constexpr bool accept([[maybe_unused]] const Entity entity) ENTT_NOEXCEPT {
         if constexpr(Enable) {
@@ -214,27 +214,14 @@ struct stable_iteration {
  */
 
 
-/*! @brief Stable storage policy, aimed at pointer stability. */
-using packed_storage_policy = internal::stable_iteration<false>;
-
-
-/*! @brief Packed storage policy, aimed at faster linear iteration. */
-using stable_storage_policy = internal::stable_iteration<true>;
-
-
 /**
  * @brief View implementation.
  *
  * Primary template isn't defined on purpose. All the specializations give a
  * compile-time error, but for a few reasonable cases.
  */
-template<typename...>
-class basic_view_impl;
-
-
-/*! @brief View implementation dispatcher. */
-template<typename...>
-struct basic_view;
+template<typename, typename, typename, typename>
+class basic_view;
 
 
 /**
@@ -266,28 +253,25 @@ struct basic_view;
  * Lifetime of a view must not overcome that of the registry that generated it.
  * In any other case, attempting to use a view results in undefined behavior.
  *
- * @tparam Policy Common (stricter) storage policy.
  * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the view.
  * @tparam Component Types of components iterated by the view.
+ * @tparam Exclude Types of components used to filter the view.
  */
-template<typename Policy, typename Entity, typename... Exclude, typename... Component>
-class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
-    template<typename Comp>
-    using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
-
-    using basic_common_type = std::common_type_t<typename storage_type<Component>::base_type...>;
+template<typename Entity, typename... Component, typename... Exclude>
+class basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> {
+    using basic_common_type = std::common_type_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type::base_type...>;
+    using policy_type = internal::policy_dispatcher<(in_place_delete_v<std::remove_const_t<Component>> || ...)>;
 
     class iterable final {
         template<typename It>
         struct iterable_iterator final {
             using difference_type = std::ptrdiff_t;
-            using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view_impl>().get({})));
+            using value_type = decltype(std::tuple_cat(std::tuple<Entity>{}, std::declval<basic_view>().get({})));
             using pointer = void;
             using reference = value_type;
             using iterator_category = std::input_iterator_tag;
 
-            iterable_iterator(It from, const basic_view_impl *parent) ENTT_NOEXCEPT
+            iterable_iterator(It from, const basic_view *parent) ENTT_NOEXCEPT
                 : it{from},
                   view{parent}
             {}
@@ -315,14 +299,14 @@ class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
 
         private:
             It it;
-            const basic_view_impl *view;
+            const basic_view *view;
         };
 
     public:
-        using iterator = iterable_iterator<internal::view_iterator<Policy, basic_common_type, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
-        using reverse_iterator = iterable_iterator<internal::view_iterator<Policy, basic_common_type, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>>;
+        using iterator = iterable_iterator<internal::view_iterator<basic_common_type, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude), policy_type>>;
+        using reverse_iterator = iterable_iterator<internal::view_iterator<basic_common_type, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude), policy_type>>;
 
-        iterable(const basic_view_impl &parent)
+        iterable(const basic_view &parent)
             : view{parent}
         {}
 
@@ -343,7 +327,7 @@ class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
         }
 
     private:
-        const basic_view_impl view;
+        const basic_view view;
     };
 
     [[nodiscard]] const auto * candidate() const ENTT_NOEXCEPT {
@@ -371,11 +355,11 @@ class basic_view_impl<Policy, Entity, exclude_t<Exclude...>, Component...> {
     template<typename Comp, typename Func>
     void traverse(Func func) const {
         for(const auto curr: internal::iterable_storage<Entity, Comp>{*std::get<storage_type<Comp> *>(pools)}) {
-            if(internal::stable_iteration<in_place_delete_v<std::remove_const_t<Comp>>>::accept(std::get<0>(curr))
+            if(internal::policy_dispatcher<in_place_delete_v<std::remove_const_t<Comp>>>::accept(std::get<0>(curr))
                 && ((std::is_same_v<Comp, Component> || std::get<storage_type<Component> *>(pools)->contains(std::get<0>(curr))) && ...)
                 && std::apply([entt = std::get<0>(curr)](const auto *... cpool) { return (!cpool->contains(entt) && ...); }, filter))
             {
-                if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view_impl>().get({})))>) {
+                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(std::get<0>(curr)), dispatch_get<Comp, Component>(curr)...));
                 } else {
                     std::apply(func, std::tuple_cat(dispatch_get<Comp, Component>(curr)...));
@@ -390,14 +374,21 @@ public:
     /*! @brief Unsigned integer type. */
     using size_type = std::size_t;
     /*! @brief Bidirectional iterator type. */
-    using iterator = internal::view_iterator<Policy, basic_common_type, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
+    using iterator = internal::view_iterator<basic_common_type, typename basic_common_type::iterator, sizeof...(Component) - 1u, sizeof...(Exclude), policy_type>;
     /*! @brief Reverse iterator type. */
-    using reverse_iterator = internal::view_iterator<Policy, basic_common_type, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude)>;
+    using reverse_iterator = internal::view_iterator<basic_common_type, typename basic_common_type::reverse_iterator, sizeof...(Component) - 1u, sizeof...(Exclude), policy_type>;
     /*! @brief Iterable view type. */
     using iterable_view = iterable;
 
+    /**
+     * @brief Storage type associated with a given component.
+     * @tparam Type Type of component.
+     */
+    template<typename Comp>
+    using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
+
     /*! @brief Default constructor to use to create empty, invalid views. */
-    basic_view_impl() ENTT_NOEXCEPT
+    basic_view() ENTT_NOEXCEPT
         : pools{},
           filter{},
           view{}
@@ -408,7 +399,7 @@ public:
      * @param component The storage for the types to iterate.
      * @param epool The storage for the types used to filter the view.
      */
-    basic_view_impl(storage_type<Component> &... component, const storage_type<Exclude> &... epool) ENTT_NOEXCEPT
+    basic_view(storage_type<Component> &... component, const storage_type<Exclude> &... epool) ENTT_NOEXCEPT
         : pools{&component...},
           filter{&epool...},
           view{candidate()}
@@ -645,14 +636,14 @@ public:
     /**
      * @brief Combines two views in a _more specific_ one (friend function).
      * @tparam Id A valid entity type (see entt_traits for more details).
-     * @tparam ELhs Filter list of the first view.
      * @tparam CLhs Component list of the first view.
-     * @tparam ERhs Filter list of the second view.
+     * @tparam ELhs Filter list of the first view.
      * @tparam CRhs Component list of the second view.
+     * @tparam ERhs Filter list of the second view.
      * @return A more specific view.
      */
-    template<typename Id, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
-    friend auto operator|(const basic_view<Id, exclude_t<ELhs...>, CLhs...> &, const basic_view<Id, exclude_t<ERhs...>, CRhs...> &);
+    template<typename Id, typename... CLhs, typename... ELhs, typename... CRhs, typename... ERhs>
+    friend auto operator|(const basic_view<Id, get_t<CLhs...>, exclude_t<ELhs...>> &, const basic_view<Id, get_t<CRhs...>, exclude_t<ERhs...>> &);
 
 private:
     const std::tuple<storage_type<Component> *...> pools;
@@ -693,9 +684,11 @@ private:
  * @tparam Component Type of component iterated by the view.
  */
 template<typename Entity, typename Component>
-class basic_view_impl<packed_storage_policy, Entity, exclude_t<>, Component> {
-    using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
-    using basic_common_type = typename storage_type::base_type;
+class basic_view<Entity, get_t<Component>, exclude_t<>, 
+    // Yeah, there is a reason why void_t and enable_if_t were combined here. Try removing the first one and let me know. :)
+    std::void_t<std::enable_if_t<!in_place_delete_v<std::remove_const_t<Component>>>>
+> {
+    using basic_common_type = typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type::base_type;
 
 public:
     /*! @brief Underlying entity identifier. */
@@ -708,9 +701,11 @@ public:
     using reverse_iterator = typename basic_common_type::reverse_iterator;
     /*! @brief Iterable view type. */
     using iterable_view = internal::iterable_storage<Entity, Component>;
+    /*! @brief Storage type associated with the view component. */
+    using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
 
     /*! @brief Default constructor to use to create empty, invalid views. */
-    basic_view_impl() ENTT_NOEXCEPT
+    basic_view() ENTT_NOEXCEPT
         : pools{},
           filter{}
     {}
@@ -719,7 +714,7 @@ public:
      * @brief Constructs a single-type view from a storage class.
      * @param ref The storage for the type to iterate.
      */
-    basic_view_impl(storage_type &ref) ENTT_NOEXCEPT
+    basic_view(storage_type &ref) ENTT_NOEXCEPT
         : pools{&ref},
           filter{}
     {}
@@ -963,14 +958,14 @@ public:
     /**
      * @brief Combines two views in a _more specific_ one (friend function).
      * @tparam Id A valid entity type (see entt_traits for more details).
-     * @tparam ELhs Filter list of the first view.
      * @tparam CLhs Component list of the first view.
-     * @tparam ERhs Filter list of the second view.
+     * @tparam ELhs Filter list of the first view.
      * @tparam CRhs Component list of the second view.
+     * @tparam ERhs Filter list of the second view.
      * @return A more specific view.
      */
-    template<typename Id, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
-    friend auto operator|(const basic_view<Id, exclude_t<ELhs...>, CLhs...> &, const basic_view<Id, exclude_t<ERhs...>, CRhs...> &);
+    template<typename Id, typename... CLhs, typename... ELhs, typename... CRhs, typename... ERhs>
+    friend auto operator|(const basic_view<Id, get_t<CLhs...>, exclude_t<ELhs...>> &, const basic_view<Id, get_t<CRhs...>, exclude_t<ERhs...>> &);
 
 private:
     const std::tuple<storage_type *> pools;
@@ -978,22 +973,6 @@ private:
 };
 
 
-/**
- * @brief View implementation dispatcher.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam Exclude Types of components used to filter the view.
- * @tparam Component Types of components iterated by the view.
- */
-template<typename Entity, typename... Exclude, typename... Component>
-struct basic_view<Entity, exclude_t<Exclude...>, Component...>
-    : basic_view_impl<internal::stable_iteration<(in_place_delete_v<std::remove_const_t<Component>> || ...)>, Entity, exclude_t<Exclude...>, Component...>
-{
-    /*! @brief Most restrictive storage policy of all component types. */
-    using storage_policy = internal::stable_iteration<(in_place_delete_v<std::remove_const_t<Component>> || ...)>;
-    using basic_view_impl<storage_policy, Entity, exclude_t<Exclude...>, Component...>::basic_view_impl;
-};
-
-
 /**
  * @brief Deduction guide.
  * @tparam Storage Type of storage classes used to create the view.
@@ -1001,23 +980,23 @@ struct basic_view<Entity, exclude_t<Exclude...>, Component...>
  */
 template<typename... Storage>
 basic_view(Storage &... storage)
--> basic_view<std::common_type_t<typename Storage::entity_type...>, exclude_t<>, constness_as_t<typename Storage::value_type, Storage>...>;
+-> basic_view<std::common_type_t<typename Storage::entity_type...>, get_t<constness_as_t<typename Storage::value_type, Storage>...>, exclude_t<>>;
 
 
 /**
  * @brief Combines two views in a _more specific_ one.
  * @tparam Entity A valid entity type (see entt_traits for more details).
- * @tparam ELhs Filter list of the first view.
  * @tparam CLhs Component list of the first view.
- * @tparam ERhs Filter list of the second view.
+ * @tparam ELhs Filter list of the first view.
  * @tparam CRhs Component list of the second view.
+ * @tparam ERhs Filter list of the second view.
  * @param lhs A valid reference to the first view.
  * @param rhs A valid reference to the second view.
  * @return A more specific view.
  */
-template<typename Entity, typename... ELhs, typename... CLhs, typename... ERhs, typename... CRhs>
-[[nodiscard]] auto operator|(const basic_view<Entity, exclude_t<ELhs...>, CLhs...> &lhs, const basic_view<Entity, exclude_t<ERhs...>, CRhs...> &rhs) {
-    using view_type = basic_view<Entity, exclude_t<ELhs..., ERhs...>, CLhs..., CRhs...>;
+template<typename Entity, typename... CLhs, typename... ELhs, typename... CRhs, typename... ERhs>
+[[nodiscard]] auto operator|(const basic_view<Entity, get_t<CLhs...>, exclude_t<ELhs...>> &lhs, const basic_view<Entity, get_t<CRhs...>, exclude_t<ERhs...>> &rhs) {
+    using view_type = basic_view<Entity, get_t<CLhs..., CRhs...>, exclude_t<ELhs..., ERhs...>>;
     return std::make_from_tuple<view_type>(std::tuple_cat(
         std::apply([](auto *... curr) { return std::forward_as_tuple(*curr...); }, lhs.pools),
         std::apply([](auto *... curr) { return std::forward_as_tuple(*curr...); }, rhs.pools),

+ 7 - 7
test/entt/entity/helper.cpp

@@ -14,19 +14,19 @@ TEST(Helper, AsView) {
     entt::registry registry;
     const entt::registry cregistry;
 
-    ([](entt::view<entt::exclude_t<>, int>) {})(entt::as_view{registry});
-    ([](entt::view<entt::exclude_t<int>, char, double>) {})(entt::as_view{registry});
-    ([](entt::view<entt::exclude_t<int>, const char, double>) {})(entt::as_view{registry});
-    ([](entt::view<entt::exclude_t<int>, const char, const double>) {})(entt::as_view{cregistry});
+    ([](entt::view<entt::get_t<int>>) {})(entt::as_view{registry});
+    ([](entt::view<entt::get_t<char, double>, entt::exclude_t<int>>) {})(entt::as_view{registry});
+    ([](entt::view<entt::get_t<const char, double>, entt::exclude_t<int>>) {})(entt::as_view{registry});
+    ([](entt::view<entt::get_t<const char, const double>, entt::exclude_t<int>>) {})(entt::as_view{cregistry});
 }
 
 TEST(Helper, AsGroup) {
     entt::registry registry;
     const entt::registry cregistry;
 
-    ([](entt::group<entt::exclude_t<int>, entt::get_t<char>, double>) {})(entt::as_group{registry});
-    ([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, double>) {})(entt::as_group{registry});
-    ([](entt::group<entt::exclude_t<int>, entt::get_t<const char>, const double>) {})(entt::as_group{cregistry});
+    ([](entt::group<entt::owned_t<double>, entt::get_t<char>, entt::exclude_t<int>>) {})(entt::as_group{registry});
+    ([](entt::group<entt::owned_t<double>, entt::get_t<const char>, entt::exclude_t<int>>) {})(entt::as_group{registry});
+    ([](entt::group<entt::owned_t<const double>, entt::get_t<const char>, entt::exclude_t<int>>) {})(entt::as_group{cregistry});
 }
 
 TEST(Helper, Invoke) {

+ 14 - 14
test/entt/entity/organizer.cpp

@@ -2,24 +2,24 @@
 #include <entt/entity/organizer.hpp>
 #include <entt/entity/registry.hpp>
 
-void ro_int_rw_char_double(entt::view<entt::exclude_t<>, const int, char>, double &) {}
-void ro_char_rw_int(entt::view<entt::exclude_t<>, int, const char>) {}
-void ro_char_rw_double(entt::view<entt::exclude_t<>, const char>, double &) {}
-void ro_int_double(entt::view<entt::exclude_t<>, const int>, const double &) {}
-void sync_point(entt::registry &, entt::view<entt::exclude_t<>, const int>) {}
+void ro_int_rw_char_double(entt::view<entt::get_t<const int, char>>, double &) {}
+void ro_char_rw_int(entt::view<entt::get_t<int, const char>>) {}
+void ro_char_rw_double(entt::view<entt::get_t<const char>>, double &) {}
+void ro_int_double(entt::view<entt::get_t<const int>>, const double &) {}
+void sync_point(entt::registry &, entt::view<entt::get_t<const int>>) {}
 
 struct clazz {
-    void ro_int_char_double(entt::view<entt::exclude_t<>, const int, const char>, const double &) {}
-    void rw_int(entt::view<entt::exclude_t<>, int>) {}
-    void rw_int_char(entt::view<entt::exclude_t<>, int, char>) {}
-    void rw_int_char_double(entt::view<entt::exclude_t<>, int, char>, double &) {}
-
-    static void ro_int_with_payload(const clazz &, entt::view<entt::exclude_t<>, const int>) {}
-    static void ro_char_with_payload(const clazz &, entt::view<entt::exclude_t<>, const char>) {}
-    static void ro_int_char_with_payload(clazz &, entt::view<entt::exclude_t<>, const int, const char>) {}
+    void ro_int_char_double(entt::view<entt::get_t<const int, const char>>, const double &) {}
+    void rw_int(entt::view<entt::get_t<int>>) {}
+    void rw_int_char(entt::view<entt::get_t<int, char>>) {}
+    void rw_int_char_double(entt::view<entt::get_t<int, char>>, double &) {}
+
+    static void ro_int_with_payload(const clazz &, entt::view<entt::get_t<const int>>) {}
+    static void ro_char_with_payload(const clazz &, entt::view<entt::get_t<const char>>) {}
+    static void ro_int_char_with_payload(clazz &, entt::view<entt::get_t<const int, const char>>) {}
 };
 
-void to_args_integrity(entt::view<entt::exclude_t<>, int> view, std::size_t &value, entt::registry &registry) {
+void to_args_integrity(entt::view<entt::get_t<int>> view, std::size_t &value, entt::registry &registry) {
     value = view.size();
 }
 

+ 10 - 23
test/entt/entity/view.cpp

@@ -392,13 +392,9 @@ TEST(SingleComponentView, DeductionGuide) {
     typename entt::storage_traits<entt::entity, int>::storage_type istorage;
     typename entt::storage_traits<entt::entity, stable_type>::storage_type sstorage;
 
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, int>, decltype(entt::basic_view{istorage})>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, const int>, decltype(entt::basic_view{std::as_const(istorage)})>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, stable_type>, decltype(entt::basic_view{sstorage})>);
-
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<>, int>, decltype(entt::basic_view{istorage})>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<>, const int>, decltype(entt::basic_view{std::as_const(istorage)})>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::stable_storage_policy, entt::entity, entt::exclude_t<>, stable_type>, decltype(entt::basic_view{sstorage})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int>, entt::exclude_t<>>, decltype(entt::basic_view{istorage})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const int>, entt::exclude_t<>>, decltype(entt::basic_view{std::as_const(istorage)})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<stable_type>, entt::exclude_t<>>, decltype(entt::basic_view{sstorage})>);
 }
 
 TEST(SingleComponentView, IterableViewAlgorithmCompatibility) {
@@ -1001,17 +997,11 @@ TEST(MultiComponentView, DeductionGuide) {
     typename entt::storage_traits<entt::entity, double>::storage_type dstorage;
     typename entt::storage_traits<entt::entity, stable_type>::storage_type sstorage;
 
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, int, double>, decltype(entt::basic_view{istorage, dstorage})>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, const int, double>, decltype(entt::basic_view{std::as_const(istorage), dstorage})>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, int, const double>, decltype(entt::basic_view{istorage, std::as_const(dstorage)})>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, const int, const double>, decltype(entt::basic_view{std::as_const(istorage), std::as_const(dstorage)})>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<>, int, stable_type>, decltype(entt::basic_view{istorage, sstorage})>);
-
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<>, int, double>, decltype(entt::basic_view{istorage, dstorage})>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<>, const int, double>, decltype(entt::basic_view{std::as_const(istorage), dstorage})>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<>, int, const double>, decltype(entt::basic_view{istorage, std::as_const(dstorage)})>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<>, const int, const double>, decltype(entt::basic_view{std::as_const(istorage), std::as_const(dstorage)})>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::stable_storage_policy, entt::entity, entt::exclude_t<>, int, stable_type>, decltype(entt::basic_view{istorage, sstorage})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, double>, entt::exclude_t<>>, decltype(entt::basic_view{istorage, dstorage})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const int, double>, entt::exclude_t<>>, decltype(entt::basic_view{std::as_const(istorage), dstorage})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, const double>, entt::exclude_t<>>, decltype(entt::basic_view{istorage, std::as_const(dstorage)})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const int, const double>, entt::exclude_t<>>, decltype(entt::basic_view{std::as_const(istorage), std::as_const(dstorage)})>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, stable_type>, entt::exclude_t<>>, decltype(entt::basic_view{istorage, sstorage})>);
 }
 
 TEST(MultiComponentView, IterableViewAlgorithmCompatibility) {
@@ -1095,13 +1085,10 @@ TEST(View, Pipe) {
     const auto view3 = registry.view<empty_type>();
     const auto view4 = registry.view<stable_type>();
 
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<double, float>, int, const char>, decltype(view1 | view2)>);
-    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::exclude_t<float, double>, const char, int>, decltype(view2 | view1)>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, const char>, entt::exclude_t<double, float>>, decltype(view1 | view2)>);
+    static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const char, int>, entt::exclude_t<float, double>>, decltype(view2 | view1)>);
     static_assert(std::is_same_v<decltype((view1 | view2) | view3), decltype(view1 | (view2 | view3))>);
 
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::packed_storage_policy, entt::entity, entt::exclude_t<double, float>, int, const char>, decltype(view1 | view2)>);
-    static_assert(std::is_base_of_v<entt::basic_view_impl<entt::stable_storage_policy, entt::entity, entt::exclude_t<double, float>, int, stable_type, const char>, decltype(view1 | view4 | view2)>);
-
     ASSERT_FALSE((view1 | view2).contains(entity));
     ASSERT_TRUE((view1 | view2).contains(other));