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:
11
TODO
11
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>);
|
||||
}
|
||||
|
||||
@@ -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});
|
||||
|
||||
Reference in New Issue
Block a user