Explorar el Código

component/storage:
* removed ignore_if_empty_v, added ignore_as_empty_v
* removed fake getter requirement for empty storage types

Michele Caini hace 4 años
padre
commit
88da5261fc

+ 1 - 1
src/entt/entity/component.hpp

@@ -41,7 +41,7 @@ inline constexpr bool in_place_delete_v = component_traits<Type>::in_place_delet
  * @tparam Type Type of component.
  */
 template<class Type>
-inline constexpr bool ignore_if_empty_v = component_traits<Type>::ignore_if_empty::value;
+inline constexpr bool ignore_as_empty_v = component_traits<Type>::ignore_if_empty::value && std::is_empty_v<Type>;
 
 
 }

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

@@ -591,11 +591,11 @@ class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> final
     public:
         using iterator = iterable_iterator<
             typename basic_common_type::iterator,
-            type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().end())>>...>
+            type_list_cat_t<std::conditional_t<ignore_as_empty_v<std::remove_const_t<Owned>>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().end())>>...>
         >;
         using reverse_iterator = iterable_iterator<
             typename basic_common_type::reverse_iterator,
-            type_list_cat_t<std::conditional_t<std::is_void_v<decltype(std::declval<storage_type<Owned>>().get({}))>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().rbegin())>>...>
+            type_list_cat_t<std::conditional_t<ignore_as_empty_v<std::remove_const_t<Owned>>, type_list<>, type_list<decltype(std::declval<storage_type<Owned>>().rbegin())>>...>
         >;
 
         iterable(std::tuple<storage_type<Owned> *..., storage_type<Get> *...> cpools, const std::size_t * const extent)

+ 9 - 5
src/entt/entity/registry.hpp

@@ -1438,12 +1438,16 @@ public:
         ENTT_ASSERT(sortable<Component>(), "Cannot sort owned storage");
         auto *cpool = assure<Component>();
 
-        if constexpr(std::is_invocable_v<Compare, decltype(cpool->get({})), decltype(cpool->get({}))>) {
-            cpool->sort([this, cpool, compare = std::move(compare)](const auto lhs, const auto rhs) {
-                return compare(std::as_const(cpool->get(lhs)), std::as_const(cpool->get(rhs)));
-            }, std::move(algo), std::forward<Args>(args)...);
-        } else {
+        if constexpr(ignore_as_empty_v<Component>) {
             cpool->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
+        } else {
+            if constexpr(std::is_invocable_v<Compare, decltype(cpool->get({})), decltype(cpool->get({}))>) {
+                cpool->sort([this, cpool, compare = std::move(compare)](const auto lhs, const auto rhs) {
+                    return compare(std::as_const(cpool->get(lhs)), std::as_const(cpool->get(rhs)));
+                }, std::move(algo), std::forward<Args>(args)...);
+            } else {
+                cpool->sort(std::move(compare), std::move(algo), std::forward<Args>(args)...);
+            }
         }
     }
 

+ 10 - 17
src/entt/entity/storage.hpp

@@ -667,7 +667,7 @@ private:
 
 /*! @copydoc basic_storage */
 template<typename Entity, typename Type, typename Allocator>
-class basic_storage<Entity, Type, Allocator, std::enable_if_t<component_traits<Type>::ignore_if_empty::value && std::is_empty_v<Type>>>
+class basic_storage<Entity, Type, Allocator, std::enable_if_t<ignore_as_empty_v<Type>>>
     : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>>
 {
     using allocator_traits = std::allocator_traits<Allocator>;
@@ -700,19 +700,6 @@ public:
         return allocator_type{underlying_type::get_allocator()};
     }
 
-    /**
-     * @brief Fake get function.
-     *
-     * @warning
-     * Attempting to use an entity that doesn't belong to the storage results in
-     * undefined behavior.
-     *
-     * @param entt A valid entity identifier.
-     */
-    void get([[maybe_unused]] const entity_type entt) const ENTT_NOEXCEPT {
-        ENTT_ASSERT(underlying_type::contains(entt), "Storage does not contain entity");
-    }
-
     /**
      * @brief Assigns an entity to a storage and constructs its object.
      *
@@ -923,7 +910,10 @@ public:
     decltype(auto) emplace(basic_registry<entity_type> &owner, const entity_type entt, Args &&... args) {
         Type::emplace(entt, std::forward<Args>(args)...);
         construction.publish(owner, entt);
-        return this->get(entt);
+
+        if constexpr(!ignore_as_empty_v<value_type>) {
+            return this->get(entt);
+        }
     }
 
     /**
@@ -960,7 +950,10 @@ public:
     decltype(auto) patch(basic_registry<entity_type> &owner, const entity_type entt, Func &&... func) {
         Type::patch(entt, std::forward<Func>(func)...);
         update.publish(owner, entt);
-        return this->get(entt);
+
+        if constexpr(!ignore_as_empty_v<value_type>) {
+            return this->get(entt);
+        }
     }
 
 private:
@@ -993,7 +986,7 @@ template<typename Type>
 [[nodiscard]] auto get_as_tuple([[maybe_unused]] Type &container, [[maybe_unused]] const typename Type::entity_type entt) {
     static_assert(std::is_same_v<std::remove_const_t<Type>, typename storage_traits<typename Type::entity_type, typename Type::value_type>::storage_type>, "Invalid storage");
 
-    if constexpr(std::is_void_v<decltype(container.get({}))>) {
+    if constexpr(ignore_as_empty_v<typename Type::value_type>) {
         return std::make_tuple();
     } else {
         return std::forward_as_tuple(container.get(entt));

+ 3 - 5
src/entt/entity/view.hpp

@@ -35,8 +35,6 @@ class iterable_storage final {
     using basic_common_type = basic_sparse_set<Entity>;
     using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
 
-    static constexpr bool has_void_getter = std::is_void_v<decltype(std::declval<storage_type>().get({}))>;
-
     template<typename... It>
     struct iterable_storage_iterator final {
         using difference_type = std::ptrdiff_t;
@@ -77,12 +75,12 @@ class iterable_storage final {
 
 public:
     using iterator = std::conditional_t<
-        has_void_getter,
+        ignore_as_empty_v<std::remove_const_t<Component>>,
         iterable_storage_iterator<typename basic_common_type::iterator>,
         iterable_storage_iterator<typename basic_common_type::iterator, decltype(std::declval<storage_type>().begin())>
     >;
     using reverse_iterator = std::conditional_t<
-        has_void_getter,
+        ignore_as_empty_v<std::remove_const_t<Component>>,
         iterable_storage_iterator<typename basic_common_type::reverse_iterator>,
         iterable_storage_iterator<typename basic_common_type::reverse_iterator, decltype(std::declval<storage_type>().rbegin())>
     >;
@@ -923,7 +921,7 @@ public:
      */
     template<typename Func>
     void each(Func func) const {
-        if constexpr(std::is_void_v<decltype(std::get<0>(pools)->get({}))>) {
+        if constexpr(ignore_as_empty_v<std::remove_const_t<Component>>) {
             if constexpr(std::is_invocable_v<Func>) {
                 for(auto pos = size(); pos; --pos) {
                     func();