Bladeren bron

component_traits:
* removed ::ignore_if_empty member
* use ::page_size 0 for empty types

Michele Caini 4 jaren geleden
bovenliggende
commit
805bb84c8f
6 gewijzigde bestanden met toevoegingen van 28 en 44 verwijderingen
  1. 2 3
      TODO
  2. 7 9
      docs/md/entity.md
  3. 3 19
      src/entt/entity/component.hpp
  4. 3 5
      src/entt/entity/storage.hpp
  5. 13 7
      test/entt/entity/component.cpp
  6. 0 1
      test/entt/entity/storage.cpp

+ 2 - 3
TODO

@@ -3,13 +3,12 @@
 * add examples (and credits) from @alanjfs :)
 
 WIP:
-* uses-allocator construction: dense map, compressed pair, any (with allocator support), cache, dispatcher, poly, storage/map/allocate_unique (with uninitialized_construct_using_allocator/construct_at), ...
+* get rid of storage_traits class template
+* uses-allocator construction: any (with allocator support), cache, dispatcher, poly, ...
 * add an ENTT_NOEXCEPT with args and use it to make ie compressed_pair conditionally noexcept
-* storage traits: mixin only, make views stop using traits, they can refer to storage<T> only
 * process scheduler: reviews, use free lists internally
 * runtime events (emitter)
 * iterator based try_emplace vs try_insert for perf reasons
-* registry: remove reference to basic_sparse_set<E>
 * dedicated entity storage, in-place O(1) release/destroy for non-orphaned entities, out-of-sync model
 * entity-only and exclude-only views
 * custom allocators all over

+ 7 - 9
docs/md/entity.md

@@ -955,9 +955,8 @@ of `component_traits` implements all the required functionalities.<br/>
 The non-specialized version of this class contains the following members:
 
 * `in_place_delete`: `Type::in_place_delete` if present, false otherwise.
-* `ignore_if_empty`: `Type::ignore_if_empty` if present, `ENTT_IGNORE_IF_EMPTY`
-  otherwise.
-* `page_size`: `Type::page_size` if present, `ENTT_PACKED_PAGE` otherwise.
+* `page_size`: `Type::page_size` if present, `ENTT_PACKED_PAGE` (for non-empty
+  types) or 0 (for empty types) otherwise.
 
 Where `Type` is any type of component. All properties can be customized by
 specializing the above class and defining all its members, or by adding only
@@ -2061,7 +2060,7 @@ groups or as free types with multi type views and groups in general.
 
 # Empty type optimization
 
-An empty type `T` is such that `std::is_empty_v<T>` returns true. They are also
+An empty type `T` is such that `std::is_empty_v<T>` returns true. They also are
 the same types for which _empty base optimization_ (EBO) is possible.<br/>
 `EnTT` handles these types in a special way, optimizing both in terms of
 performance and memory usage. However, this also has consequences that are worth
@@ -2078,11 +2077,10 @@ it is assigned to.
 
 More in general, none of the feature offered by the library is affected, but for
 the ones that require to return actual instances.<br/>
-This optimization can be disabled for the whole application by defining the
-`ENTT_NO_ETO` macro. In this case, empty types will be treated like all other
-types. Otherwise, users can also specialize the `component_traits` template
-class and in particular the `ignore_if_empty` alias, disabling this optimization
-for some types only.
+This optimization is disabled by defining the `ENTT_NO_ETO` macro. In this case,
+empty types are treated like all other types. Setting a page size at component
+level via the `component_traits` class template is another way to disable this
+optimization selectively rather than globally.
 
 # Multithreading
 

+ 3 - 19
src/entt/entity/component.hpp

@@ -21,15 +21,8 @@ template<typename Type>
 struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>>
     : std::true_type {};
 
-template<typename, typename = void>
-struct ignore_if_empty: std::bool_constant<ENTT_IGNORE_IF_EMPTY> {};
-
-template<typename Type>
-struct ignore_if_empty<Type, std::enable_if_t<Type::ignore_if_empty>>
-    : std::true_type {};
-
-template<typename, typename = void>
-struct page_size: std::integral_constant<std::size_t, ENTT_PACKED_PAGE> {};
+template<typename Type, typename = void>
+struct page_size: std::integral_constant<std::size_t, (ENTT_IGNORE_IF_EMPTY && std::is_empty_v<Type>) ? 0u : ENTT_PACKED_PAGE> {};
 
 template<typename Type>
 struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::page_size), std::size_t>>>
@@ -52,19 +45,10 @@ struct component_traits {
 
     /*! @brief Pointer stability, default is `false`. */
     static constexpr bool in_place_delete = internal::in_place_delete<Type>::value;
-    /*! @brief Empty type optimization, default is `ENTT_IGNORE_IF_EMPTY`. */
-    static constexpr bool ignore_if_empty = internal::ignore_if_empty<Type>::value;
-    /*! @brief Page size, default is `ENTT_PACKED_PAGE`. */
+    /*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */
     static constexpr std::size_t page_size = internal::page_size<Type>::value;
 };
 
-/**
- * @brief Helper variable template.
- * @tparam Type Type of component.
- */
-template<class Type>
-inline constexpr bool ignore_as_empty_v = component_traits<Type>::ignore_if_empty &&std::is_empty_v<Type>;
-
 } // namespace entt
 
 #endif

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

@@ -234,10 +234,9 @@ template<typename Entity, typename Type, typename Allocator, typename>
 class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
     using alloc_traits = std::allocator_traits<Allocator>;
     static_assert(std::is_same_v<typename alloc_traits::value_type, Type>);
-
-    using comp_traits = component_traits<Type>;
     using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
     using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
+    using comp_traits = component_traits<Type>;
 
     [[nodiscard]] auto &element_at(const std::size_t pos) const {
         return packed.first()[pos / comp_traits::page_size][fast_mod(pos, comp_traits::page_size)];
@@ -744,13 +743,12 @@ private:
 
 /*! @copydoc basic_storage */
 template<typename Entity, typename Type, typename Allocator>
-class basic_storage<Entity, Type, Allocator, std::enable_if_t<ignore_as_empty_v<Type>>>
+class basic_storage<Entity, Type, Allocator, std::enable_if_t<component_traits<Type>::page_size == 0u>>
     : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> {
     using alloc_traits = std::allocator_traits<Allocator>;
     static_assert(std::is_same_v<typename alloc_traits::value_type, Type>);
-
-    using comp_traits = component_traits<Type>;
     using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
+    using comp_traits = component_traits<Type>;
 
 public:
     /*! @brief Base type. */

+ 13 - 7
test/entt/entity/component.cpp

@@ -11,17 +11,25 @@ struct traits_based {};
 template<>
 struct entt::component_traits<traits_based> {
     static constexpr auto in_place_delete = false;
-    static constexpr auto ignore_if_empty = false;
     static constexpr auto page_size = 8u;
 };
 
-struct default_params {};
+struct default_params_empty {};
+struct default_params_non_empty {
+    int value;
+};
+
+TEST(Component, DefaultParamsEmpty) {
+    using traits = entt::component_traits<default_params_empty>;
+
+    static_assert(!traits::in_place_delete);
+    static_assert(traits::page_size == 0u);
+}
 
-TEST(Component, DefaultParams) {
-    using traits = entt::component_traits<default_params>;
+TEST(Component, DefaultParamsNonEmpty) {
+    using traits = entt::component_traits<default_params_non_empty>;
 
     static_assert(!traits::in_place_delete);
-    static_assert(traits::ignore_if_empty);
     static_assert(traits::page_size == ENTT_PACKED_PAGE);
 }
 
@@ -29,7 +37,6 @@ TEST(Component, SelfContained) {
     using traits = entt::component_traits<self_contained>;
 
     static_assert(traits::in_place_delete);
-    static_assert(traits::ignore_if_empty);
     static_assert(traits::page_size == 4u);
 }
 
@@ -37,6 +44,5 @@ TEST(Component, TraitsBased) {
     using traits = entt::component_traits<traits_based>;
 
     static_assert(!traits::in_place_delete);
-    static_assert(!traits::ignore_if_empty);
     static_assert(traits::page_size == 8u);
 }

+ 0 - 1
test/entt/entity/storage.cpp

@@ -78,7 +78,6 @@ struct crete_from_constructor {
 template<>
 struct entt::component_traits<std::unordered_set<char>> {
     static constexpr auto in_place_delete = true;
-    static constexpr auto ignore_if_empty = ENTT_IGNORE_IF_EMPTY;
     static constexpr auto page_size = ENTT_PACKED_PAGE;
 };