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

config/component/storage:
* ENTT_IGNORE_IF_EMPTY is an internal def-only macro
* component_traits review to also support void type
* updated tests for component_traits
* added a non-regression test for storage<void>

Michele Caini 3 лет назад
Родитель
Сommit
dc30c29f4e
5 измененных файлов с 52 добавлено и 17 удалено
  1. 6 5
      TODO
  2. 3 5
      src/entt/config/config.h
  3. 11 3
      src/entt/entity/component.hpp
  4. 14 4
      test/entt/entity/component.cpp
  5. 18 0
      test/entt/entity/storage.cpp

+ 6 - 5
TODO

@@ -1,12 +1,17 @@
 * debugging tools (#60): the issue online already contains interesting tips on this, look at it
 * work stealing job system (see #100) + mt scheduler based on const awareness for types
-* add examples (and credits) from @alanjfs :)
 
 EXAMPLES
 * filter on runtime values/variables (not only types)
 * support to polymorphic types (see #859)
 
+DOC:
+* storage<void>
+* custom storage/view
+* examples (and credits) from @alanjfs :)
+
 WIP:
+* make utilities page_size and in_place_delete public
 * emitter: runtime handlers, allocator support (ready for both already)
 * view/group: no storage_traits dependency -> use storage instead of components for the definition
 * basic_storage::bind for cross-registry setups
@@ -16,13 +21,9 @@ WIP:
 * 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
-* remove storage::patch
 * consider removing ENTT_NOEXCEPT, use ENTT_NOEXCEPT_IF (or noexcept(...)) as appropriate in any case (ie make compressed_pair conditionally noexcept)
 * add test for maximum number of entities reached
-
-WIP:
 * add user data to type_info
-* write documentation for custom storages and views!!
 * make runtime views use opaque storage and therefore return also elements.
 * entity-aware observer, add observer functions aside observer class
 * deprecate non-owning groups in favor of owning views and view packs, introduce lazy owning views

+ 3 - 5
src/entt/config/config.h

@@ -16,7 +16,7 @@
 #ifndef ENTT_NOEXCEPT
 #    define ENTT_NOEXCEPT noexcept
 #    define ENTT_NOEXCEPT_IF(expr) noexcept(expr)
-# else
+#else
 #    define ENTT_NOEXCEPT_IF(...)
 #endif
 
@@ -48,10 +48,8 @@
 #    define ENTT_ASSERT(condition, ...) assert(condition)
 #endif
 
-#ifdef ENTT_NO_ETO
-#    define ENTT_IGNORE_IF_EMPTY false
-#else
-#    define ENTT_IGNORE_IF_EMPTY true
+#ifndef ENTT_NO_ETO
+#    define ENTT_IGNORE_IF_EMPTY
 #endif
 
 #ifdef ENTT_STANDARD_CPP

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

@@ -21,8 +21,13 @@ template<typename Type>
 struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>>
     : std::true_type {};
 
+#if defined ENTT_IGNORE_IF_EMPTY
 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> {};
+struct page_size: std::integral_constant<std::size_t, !std::is_empty_v<Type> * ENTT_PACKED_PAGE> {};
+#else
+template<typename Type, typename = void>
+struct page_size: std::integral_constant<std::size_t, ENTT_PACKED_PAGE> {};
+#endif
 
 template<typename Type>
 struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::page_size), std::size_t>>>
@@ -41,7 +46,10 @@ struct page_size<Type, std::enable_if_t<std::is_convertible_v<decltype(Type::pag
  */
 template<typename Type, typename = void>
 struct component_traits {
-    static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type");
+    static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Unsupported type");
+
+    /*! @brief Component type. */
+    using type = Type;
 
     /*! @brief Pointer stability, default is `false`. */
     static constexpr bool in_place_delete = internal::in_place_delete<Type>::value;
@@ -54,7 +62,7 @@ struct component_traits {
  * @tparam Type Type of component.
  */
 template<class Type>
-inline constexpr bool ignore_as_empty_v = (component_traits<Type>::page_size == 0u);
+inline constexpr bool ignore_as_empty_v = (std::is_void_v<Type> || component_traits<Type>::page_size == 0u);
 
 } // namespace entt
 

+ 14 - 4
test/entt/entity/component.cpp

@@ -10,6 +10,7 @@ struct traits_based {};
 
 template<>
 struct entt::component_traits<traits_based> {
+    using type = traits_based;
     static constexpr auto in_place_delete = false;
     static constexpr auto page_size = 8u;
 };
@@ -19,34 +20,43 @@ struct default_params_non_empty {
     int value;
 };
 
+TEST(Component, VoidType) {
+    using traits = entt::component_traits<void>;
+
+    static_assert(!traits::in_place_delete);
+    static_assert(entt::ignore_as_empty_v<typename traits::type>);
+    // we don't really care about this thanks to ignore_as_empty_v
+    static_assert(traits::page_size != 0u);
+}
+
 TEST(Component, DefaultParamsEmpty) {
     using traits = entt::component_traits<default_params_empty>;
 
     static_assert(!traits::in_place_delete);
+    static_assert(entt::ignore_as_empty_v<typename traits::type>);
     static_assert(traits::page_size == 0u);
-    static_assert(entt::ignore_as_empty_v<default_params_empty>);
 }
 
 TEST(Component, DefaultParamsNonEmpty) {
     using traits = entt::component_traits<default_params_non_empty>;
 
     static_assert(!traits::in_place_delete);
+    static_assert(!entt::ignore_as_empty_v<typename traits::type>);
     static_assert(traits::page_size == ENTT_PACKED_PAGE);
-    static_assert(!entt::ignore_as_empty_v<default_params_non_empty>);
 }
 
 TEST(Component, SelfContained) {
     using traits = entt::component_traits<self_contained>;
 
     static_assert(traits::in_place_delete);
+    static_assert(!entt::ignore_as_empty_v<typename traits::type>);
     static_assert(traits::page_size == 4u);
-    static_assert(!entt::ignore_as_empty_v<self_contained>);
 }
 
 TEST(Component, TraitsBased) {
     using traits = entt::component_traits<traits_based>;
 
     static_assert(!traits::in_place_delete);
+    static_assert(!entt::ignore_as_empty_v<typename traits::type>);
     static_assert(traits::page_size == 8u);
-    static_assert(!entt::ignore_as_empty_v<traits_based>);
 }

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

@@ -244,6 +244,24 @@ TEST(Storage, StableSwap) {
     ASSERT_EQ(other.get(entt::entity{42}).value, 41);
 }
 
+TEST(Storage, VoidType) {
+    entt::storage<void> pool;
+    pool.emplace(entt::entity{99});
+
+    ASSERT_EQ(pool.type(), entt::type_id<void>());
+    ASSERT_TRUE(pool.contains(entt::entity{99}));
+
+    entt::storage<void> other{std::move(pool)};
+
+    ASSERT_FALSE(pool.contains(entt::entity{99}));
+    ASSERT_TRUE(other.contains(entt::entity{99}));
+
+    pool = std::move(other);
+
+    ASSERT_TRUE(pool.contains(entt::entity{99}));
+    ASSERT_FALSE(other.contains(entt::entity{99}));
+}
+
 TEST(Storage, EmptyType) {
     entt::storage<empty_stable_type> pool;
     pool.emplace(entt::entity{99});