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>
This commit is contained in:
Michele Caini
2022-04-21 11:43:42 +02:00
parent 370865bb57
commit dc30c29f4e
5 changed files with 52 additions and 17 deletions

11
TODO
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>);
}

View File

@@ -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});