storage: element_type vs value_type for finer control

This commit is contained in:
Michele Caini
2024-03-15 09:15:50 +01:00
parent f9d509251e
commit 4e66f6bf68
9 changed files with 39 additions and 37 deletions

View File

@@ -154,7 +154,7 @@ public:
size_type cnt = 0u;
for(auto pos = 0u; pos < length; ++pos) {
cnt += ((elem[pos] == entt::type_hash<typename Owned::value_type>::value()) || ...);
cnt += ((elem[pos] == entt::type_hash<typename Owned::element_type>::value()) || ...);
}
return cnt;
@@ -284,7 +284,7 @@ class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> {
using underlying_type = typename base_type::entity_type;
template<typename Type>
static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::value_type..., typename Exclude::value_type...>>;
static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
auto pools() const noexcept {
using return_type = std::tuple<Get *...>;
@@ -697,7 +697,7 @@ class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> {
using underlying_type = typename base_type::entity_type;
template<typename Type>
static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::value_type..., typename Get::value_type..., typename Exclude::value_type...>>;
static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::element_type..., typename Get::element_type..., typename Exclude::element_type...>>;
auto pools() const noexcept {
using return_type = std::tuple<Owned *..., Get *...>;

View File

@@ -22,7 +22,7 @@ template<typename Registry>
class as_view {
template<typename... Get, typename... Exclude>
auto dispatch(get_t<Get...>, exclude_t<Exclude...>) const {
return reg.template view<constness_as_t<typename Get::value_type, Get>...>(exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>{});
return reg.template view<constness_as_t<typename Get::element_type, Get>...>(exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{});
}
public:
@@ -62,9 +62,9 @@ class as_group {
template<typename... Owned, typename... Get, typename... Exclude>
auto dispatch(owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>) const {
if constexpr(std::is_const_v<registry_type>) {
return reg.template group_if_exists<typename Owned::value_type...>(get_t<typename Get::value_type...>{}, exclude_t<typename Exclude::value_type...>{});
return reg.template group_if_exists<typename Owned::element_type...>(get_t<typename Get::element_type...>{}, exclude_t<typename Exclude::element_type...>{});
} else {
return reg.template group<constness_as_t<typename Owned::value_type, Owned>...>(get_t<constness_as_t<typename Get::value_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::value_type, Exclude>...>{});
return reg.template group<constness_as_t<typename Owned::element_type, Owned>...>(get_t<constness_as_t<typename Get::element_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{});
}
}
@@ -125,7 +125,7 @@ void invoke(Registry &reg, const typename Registry::entity_type entt) {
* @return The entity associated with the given component.
*/
template<typename... Args>
auto to_entity(const basic_storage<Args...> &storage, const typename basic_storage<Args...>::value_type &instance) -> typename basic_storage<Args...>::entity_type {
typename basic_storage<Args...>::entity_type to_entity(const basic_storage<Args...> &storage, const typename basic_storage<Args...>::value_type &instance) {
constexpr auto page_size = basic_storage<Args...>::traits_type::page_size;
const typename basic_storage<Args...>::base_type &base = storage;
const auto *addr = std::addressof(instance);

View File

@@ -57,7 +57,7 @@ class basic_sigh_mixin final: public Type {
void pop_all() final {
if(auto &reg = owner_or_assert(); !destruction.empty()) {
for(auto it = underlying_type::base_type::begin(0), last = underlying_type::base_type::end(0); it != last; ++it) {
if constexpr(std::is_same_v<typename underlying_type::value_type, typename underlying_type::entity_type>) {
if constexpr(std::is_same_v<typename underlying_type::element_type, typename underlying_type::entity_type>) {
destruction.publish(reg, *it);
} else {
if constexpr(underlying_type::traits_type::in_place_delete) {
@@ -231,7 +231,7 @@ public:
*/
template<typename... Args>
decltype(auto) emplace(const entity_type hint, Args &&...args) {
if constexpr(std::is_same_v<typename underlying_type::value_type, typename underlying_type::entity_type>) {
if constexpr(std::is_same_v<typename underlying_type::element_type, typename underlying_type::entity_type>) {
const auto entt = underlying_type::emplace(hint, std::forward<Args>(args)...);
construction.publish(owner_or_assert(), entt);
return entt;

View File

@@ -256,7 +256,7 @@ class basic_observer: private basic_storage<Mask, typename Registry::entity_type
template<typename... Matcher, std::size_t... Index>
void connect(Registry &reg, std::index_sequence<Index...>) {
static_assert(sizeof...(Matcher) < std::numeric_limits<typename base_type::value_type>::digits, "Too many matchers");
static_assert(sizeof...(Matcher) < std::numeric_limits<Mask>::digits, "Too many matchers");
(matcher_handler<Matcher>::template connect<Index>(*this, reg), ...);
release.template connect<&basic_observer::disconnect<Matcher...>>(reg);
}

View File

@@ -52,8 +52,8 @@ struct unpack_type<const basic_registry<Args...>, type_list<Override...>>
template<typename... Get, typename... Exclude, typename... Override>
struct unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {
using ro = type_list_cat_t<type_list<typename Exclude::value_type...>, typename unpack_type<constness_as_t<typename Get::value_type, Get>, type_list<Override...>>::ro...>;
using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::value_type, Get>, type_list<Override...>>::rw...>;
using ro = type_list_cat_t<type_list<typename Exclude::element_type...>, typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::ro...>;
using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::rw...>;
};
template<typename... Get, typename... Exclude, typename... Override>

View File

@@ -375,13 +375,13 @@ protected:
*/
underlying_iterator try_emplace([[maybe_unused]] const Entity entt, [[maybe_unused]] const bool force_back, const void *value) override {
if(value) {
if constexpr(std::is_copy_constructible_v<value_type>) {
return emplace_element(entt, force_back, *static_cast<const value_type *>(value));
if constexpr(std::is_copy_constructible_v<element_type>) {
return emplace_element(entt, force_back, *static_cast<const element_type *>(value));
} else {
return base_type::end();
}
} else {
if constexpr(std::is_default_constructible_v<value_type>) {
if constexpr(std::is_default_constructible_v<element_type>) {
return emplace_element(entt, force_back);
} else {
return base_type::end();
@@ -392,10 +392,12 @@ protected:
public:
/*! @brief Base type. */
using base_type = underlying_type;
/*! @brief Element type. */
using element_type = Type;
/*! @brief Type of the objects assigned to entities. */
using value_type = Type;
using value_type = element_type;
/*! @brief Component traits. */
using traits_type = component_traits<value_type>;
using traits_type = component_traits<element_type>;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
/*! @brief Unsigned integer type. */
@@ -432,7 +434,7 @@ public:
* @param allocator The allocator to use.
*/
explicit basic_storage(const allocator_type &allocator)
: base_type{type_id<value_type>(), deletion_policy{traits_type::in_place_delete}, allocator},
: base_type{type_id<element_type>(), deletion_policy{traits_type::in_place_delete}, allocator},
payload{allocator} {}
/**
@@ -779,10 +781,10 @@ class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<T
public:
/*! @brief Base type. */
using base_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>;
/*! @brief Element type. */
using element_type = Type;
/*! @brief Type of the objects assigned to entities. */
using value_type = Type;
/*! @brief Component traits. */
using traits_type = component_traits<value_type>;
using value_type = element_type;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
/*! @brief Unsigned integer type. */
@@ -807,7 +809,7 @@ public:
* @param allocator The allocator to use.
*/
explicit basic_storage(const allocator_type &allocator)
: base_type{type_id<value_type>(), deletion_policy{traits_type::in_place_delete}, allocator} {}
: base_type{type_id<element_type>(), deletion_policy{traits_type::in_place_delete}, allocator} {}
/**
* @brief Move constructor.
@@ -836,7 +838,7 @@ public:
*/
[[nodiscard]] constexpr allocator_type get_allocator() const noexcept {
// std::allocator<void> has no cross constructors (waiting for C++20)
if constexpr(std::is_void_v<value_type> && !std::is_constructible_v<allocator_type, typename base_type::allocator_type>) {
if constexpr(std::is_void_v<element_type> && !std::is_constructible_v<allocator_type, typename base_type::allocator_type>) {
return allocator_type{};
} else {
return allocator_type{base_type::get_allocator()};
@@ -983,8 +985,8 @@ protected:
public:
/*! @brief Base type. */
using base_type = basic_sparse_set<Entity, Allocator>;
/*! @brief Type of the objects assigned to entities. */
using value_type = Entity;
/*! @brief Element type. */
using element_type = Entity;
/*! @brief Underlying entity identifier. */
using entity_type = Entity;
/*! @brief Unsigned integer type. */

View File

@@ -377,7 +377,7 @@ class basic_view<get_t<Get...>, exclude_t<Exclude...>>: public basic_common_view
using base_type = basic_common_view<std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>, sizeof...(Get), sizeof...(Exclude)>;
template<typename Type>
static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::value_type..., typename Exclude::value_type...>>;
static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>;
template<std::size_t... Index>
auto get(const typename base_type::entity_type entt, std::index_sequence<Index...>) const noexcept {
@@ -495,7 +495,7 @@ public:
*/
template<typename Type>
void storage(Type &elem) noexcept {
storage<index_of<typename Type::value_type>>(elem);
storage<index_of<typename Type::element_type>>(elem);
}
/**
@@ -797,9 +797,9 @@ public:
* @tparam Type Type of component of which to return the storage.
* @return The storage for the given component type.
*/
template<typename Type = typename Get::value_type>
template<typename Type = typename Get::element_type>
[[nodiscard]] auto *storage() const noexcept {
static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::value_type>, "Invalid component type");
static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::element_type>, "Invalid component type");
return storage<0>();
}
@@ -850,7 +850,7 @@ public:
*/
template<typename Elem>
[[nodiscard]] decltype(auto) get(const entity_type entt) const {
static_assert(std::is_same_v<std::remove_const_t<Elem>, typename Get::value_type>, "Invalid component type");
static_assert(std::is_same_v<std::remove_const_t<Elem>, typename Get::element_type>, "Invalid component type");
return get<0>(entt);
}

View File

@@ -494,11 +494,11 @@ TYPED_TEST(SighMixin, ThrowingAllocator) {
using registry_type = typename storage_type::registry_type;
storage_type pool{};
typename std::decay_t<decltype(pool)>::base_type &base = pool;
typename storage_type::base_type &base = pool;
registry_type registry;
constexpr auto packed_page_size = entt::component_traits<typename decltype(pool)::value_type>::page_size;
constexpr auto sparse_page_size = entt::entt_traits<typename decltype(pool)::entity_type>::page_size;
constexpr auto packed_page_size = entt::component_traits<typename storage_type::element_type>::page_size;
constexpr auto sparse_page_size = entt::entt_traits<typename storage_type::entity_type>::page_size;
std::size_t on_construct{};
std::size_t on_destroy{};

View File

@@ -14,7 +14,7 @@ template<typename Type>
// NOLINTNEXTLINE(*-exception-escape)
struct meta_mixin: Type {
using allocator_type = typename Type::allocator_type;
using value_type = typename Type::value_type;
using element_type = typename Type::element_type;
explicit meta_mixin(const allocator_type &allocator);
};
@@ -29,11 +29,11 @@ meta_mixin<Type>::meta_mixin(const allocator_type &allocator)
: Type{allocator} {
using namespace entt::literals;
entt::meta<value_type>()
entt::meta<element_type>()
// cross registry, same type
.template func<entt::overload<entt::storage_for_t<value_type, entt::entity> &(const entt::id_type)>(&entt::basic_registry<entt::entity>::storage<value_type>), entt::as_ref_t>("storage"_hs)
.template func<entt::overload<entt::storage_for_t<element_type, entt::entity> &(const entt::id_type)>(&entt::basic_registry<entt::entity>::storage<element_type>), entt::as_ref_t>("storage"_hs)
// cross registry, different types
.template func<entt::overload<entt::storage_for_t<value_type, my_entity> &(const entt::id_type)>(&entt::basic_registry<my_entity>::storage<value_type>), entt::as_ref_t>("storage"_hs);
.template func<entt::overload<entt::storage_for_t<element_type, my_entity> &(const entt::id_type)>(&entt::basic_registry<my_entity>::storage<element_type>), entt::as_ref_t>("storage"_hs);
}
template<typename Type>