diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index 2a47748ed..32d54d112 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -61,20 +61,20 @@ class basic_registry { template void maybe_valid_if(basic_registry &owner, const Entity entt) { - [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure()...); + [[maybe_unused]] const auto cpools = std::make_tuple(owner.assure()...); - const auto is_valid = ((std::is_same_v || std::get &>(cpools).contains(entt)) && ...) - && ((std::is_same_v || owner.assure().contains(entt)) && ...) - && ((std::is_same_v || !owner.assure().contains(entt)) && ...); + const auto is_valid = ((std::is_same_v || std::get *>(cpools)->contains(entt)) && ...) + && ((std::is_same_v || owner.assure()->contains(entt)) && ...) + && ((std::is_same_v || !owner.assure()->contains(entt)) && ...); if constexpr(sizeof...(Owned) == 0) { if(is_valid && !current.contains(entt)) { current.emplace(entt); } } else { - if(is_valid && !(std::get<0>(cpools).index(entt) < current)) { + if(is_valid && !(std::get<0>(cpools)->index(entt) < current)) { const auto pos = current++; - (std::get &>(cpools).swap(std::get &>(cpools).data()[pos], entt), ...); + (std::get *>(cpools)->swap(std::get *>(cpools)->data()[pos], entt), ...); } } } @@ -85,9 +85,9 @@ class basic_registry { current.remove(entt); } } else { - if(const auto cpools = std::forward_as_tuple(owner.assure()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) { + if(const auto cpools = std::make_tuple(owner.assure()...); std::get<0>(cpools)->contains(entt) && (std::get<0>(cpools)->index(entt) < current)) { const auto pos = --current; - (std::get &>(cpools).swap(std::get &>(cpools).data()[pos], entt), ...); + (std::get *>(cpools)->swap(std::get *>(cpools)->data()[pos], entt), ...); } } } @@ -107,7 +107,7 @@ class basic_registry { }; template - [[nodiscard]] const storage_type & assure() const { + [[nodiscard]] storage_type * assure() { const auto index = type_seq::value(); if(!(index < pools.size())) { @@ -122,12 +122,13 @@ class basic_registry { }; } - return static_cast &>(*pools[index].pool); + return static_cast *>(pools[index].pool.get()); } template - [[nodiscard]] storage_type & assure() { - return const_cast &>(std::as_const(*this).template assure()); + [[nodiscard]] const storage_type * assure() const { + const auto index = type_seq::value(); + return (!(index < pools.size()) || !pools[index].pool) ? nullptr : static_cast *>(pools[index].pool.get()); } Entity generate_identifier() { @@ -184,7 +185,8 @@ public: */ template [[nodiscard]] size_type size() const { - return assure().size(); + const auto *cpool = assure(); + return cpool ? cpool->size() : size_type{}; } /** @@ -228,7 +230,7 @@ public: if constexpr(sizeof...(Component) == 0) { entities.reserve(cap); } else { - (assure().reserve(cap), ...); + (assure()->reserve(cap), ...); } } @@ -239,7 +241,8 @@ public: */ template [[nodiscard]] size_type capacity() const { - return assure().capacity(); + const auto *cpool = assure(); + return cpool ? cpool->capacity() : size_type{}; } /** @@ -258,7 +261,7 @@ public: */ template void shrink_to_fit() { - (assure().shrink_to_fit(), ...); + (assure()->shrink_to_fit(), ...); } /** @@ -277,7 +280,7 @@ public: if constexpr(sizeof...(Component) == 0) { return !alive(); } else { - return (assure().empty() && ...); + return [](auto *... cpool) { return ((!cpool || cpool->empty()) && ...); }(assure()...); } } @@ -300,13 +303,14 @@ public: */ template [[nodiscard]] const Component * raw() const { - return assure().raw(); + const auto *cpool = assure(); + return cpool ? cpool->raw() : nullptr; } /*! @copydoc raw */ template [[nodiscard]] Component * raw() { - return const_cast(std::as_const(*this).template raw()); + return assure()->raw(); } /** @@ -324,7 +328,8 @@ public: */ template [[nodiscard]] const entity_type * data() const { - return assure().data(); + const auto *cpool = assure(); + return cpool ? cpool->data() : nullptr; } /** @@ -559,7 +564,7 @@ public: template decltype(auto) emplace(const entity_type entity, Args &&... args) { ENTT_ASSERT(valid(entity)); - return assure().emplace(*this, entity, std::forward(args)...); + return assure()->emplace(*this, entity, std::forward(args)...); } /** @@ -576,7 +581,7 @@ public: template void insert(It first, It last, const Component &value = {}) { ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); })); - assure().insert(*this, first, last, value); + assure()->insert(*this, first, last, value); } /** @@ -596,7 +601,7 @@ public: void insert(EIt first, EIt last, CIt from, CIt to) { static_assert(std::is_constructible_v::value_type>, "Invalid value type"); ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); })); - assure().insert(*this, first, last, from, to); + assure()->insert(*this, first, last, from, to); } /** @@ -622,11 +627,11 @@ public: template decltype(auto) emplace_or_replace(const entity_type entity, Args &&... args) { ENTT_ASSERT(valid(entity)); - auto &cpool = assure(); + auto *cpool = assure(); - return cpool.contains(entity) - ? cpool.patch(*this, entity, [&args...](auto &curr) { curr = Component{std::forward(args)...}; }) - : cpool.emplace(*this, entity, std::forward(args)...); + return cpool->contains(entity) + ? cpool->patch(*this, entity, [&args...](auto &curr) { curr = Component{std::forward(args)...}; }) + : cpool->emplace(*this, entity, std::forward(args)...); } /** @@ -656,7 +661,7 @@ public: template decltype(auto) patch(const entity_type entity, Func &&... func) { ENTT_ASSERT(valid(entity)); - return assure().patch(*this, entity, std::forward(func)...); + return assure()->patch(*this, entity, std::forward(func)...); } /** @@ -678,7 +683,7 @@ public: */ template decltype(auto) replace(const entity_type entity, Args &&... args) { - return assure().patch(*this, entity, [&args...](auto &curr) { curr = Component{std::forward(args)...}; }); + return assure()->patch(*this, entity, [&args...](auto &curr) { curr = Component{std::forward(args)...}; }); } /** @@ -694,7 +699,7 @@ public: template void remove(const entity_type entity) { ENTT_ASSERT(valid(entity)); - (assure().remove(*this, entity), ...); + (assure()->remove(*this, entity), ...); } /** @@ -710,7 +715,7 @@ public: template void remove(It first, It last) { ENTT_ASSERT(std::all_of(first, last, [this](const auto entity) { return valid(entity); })); - (assure().remove(*this, first, last), ...); + (assure()->remove(*this, first, last), ...); } /** @@ -735,8 +740,8 @@ public: size_type remove_if_exists(const entity_type entity) { ENTT_ASSERT(valid(entity)); - return ([this, entity](auto &&cpool) { - return cpool.contains(entity) ? (cpool.remove(*this, entity), true) : false; + return ([this, entity](auto *cpool) { + return cpool->contains(entity) ? (cpool->remove(*this, entity), true) : false; }(assure()) + ... + size_type{}); } @@ -778,7 +783,7 @@ public: template [[nodiscard]] bool has(const entity_type entity) const { ENTT_ASSERT(valid(entity)); - return (assure().contains(entity) && ...); + return [entity](auto *... cpool) { return ((cpool && cpool->contains(entity)) && ...); }(assure()...); } /** @@ -795,7 +800,7 @@ public: template [[nodiscard]] bool any(const entity_type entity) const { ENTT_ASSERT(valid(entity)); - return (assure().contains(entity) || ...); + return [entity](auto *... cpool) { return ((cpool && cpool->contains(entity)) || ...); }(assure()...); } /** @@ -814,9 +819,9 @@ public: ENTT_ASSERT(valid(entity)); if constexpr(sizeof...(Component) == 1) { - return (assure().get(entity), ...); + return (assure()->get(entity), ...); } else { - return std::forward_as_tuple(assure().get(entity)...); + return std::forward_as_tuple(assure()->get(entity)...); } } @@ -826,9 +831,9 @@ public: ENTT_ASSERT(valid(entity)); if constexpr(sizeof...(Component) == 1) { - return (assure().get(entity), ...); + return (assure()->get(entity), ...); } else { - return std::forward_as_tuple(assure().get(entity)...); + return std::forward_as_tuple(assure()->get(entity)...); } } @@ -857,8 +862,8 @@ public: template [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entity, Args &&... args) { ENTT_ASSERT(valid(entity)); - auto &cpool = assure(); - return cpool.contains(entity) ? cpool.get(entity) : cpool.emplace(*this, entity, std::forward(args)...); + auto *cpool = assure(); + return cpool->contains(entity) ? cpool->get(entity) : cpool->emplace(*this, entity, std::forward(args)...); } /** @@ -879,8 +884,8 @@ public: ENTT_ASSERT(valid(entity)); if constexpr(sizeof...(Component) == 1) { - auto &cpool = assure(); - return cpool.contains(entity) ? &cpool.get(entity) : nullptr; + auto *cpool = assure(); + return (cpool && cpool->contains(entity)) ? &cpool->get(entity) : nullptr; } else { return std::make_tuple(try_get(entity)...); } @@ -892,8 +897,8 @@ public: ENTT_ASSERT(valid(entity)); if constexpr(sizeof...(Component) == 1) { - auto &cpool = assure(); - return cpool.contains(entity) ? &cpool.get(entity) : nullptr; + auto *cpool = assure(); + return cpool->contains(entity) ? &cpool->get(entity) : nullptr; } else { return std::make_tuple(try_get(entity)...); } @@ -918,8 +923,8 @@ public: } } } else { - ([this](auto &&cpool) { - cpool.remove(*this, cpool.basic_sparse_set::begin(), cpool.basic_sparse_set::end()); + ([this](auto *cpool) { + cpool->remove(*this, cpool->basic_sparse_set::begin(), cpool->basic_sparse_set::end()); }(assure()), ...); } } @@ -1013,7 +1018,7 @@ public: */ template [[nodiscard]] auto on_construct() { - return assure().on_construct(); + return assure()->on_construct(); } /** @@ -1036,7 +1041,7 @@ public: */ template [[nodiscard]] auto on_update() { - return assure().on_update(); + return assure()->on_update(); } /** @@ -1061,7 +1066,7 @@ public: */ template [[nodiscard]] auto on_destroy() { - return assure().on_destroy(); + return assure()->on_destroy(); } /** @@ -1099,14 +1104,15 @@ public: template [[nodiscard]] basic_view, Component...> view(exclude_t = {}) const { static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported"); - return { assure>()..., assure()... }; + using view_type = basic_view, Component...>; + return [](auto *... cpools) { return (cpools && ...) ? view_type{*cpools...} : view_type{}; }(assure>()..., assure()...); } /*! @copydoc view */ template [[nodiscard]] basic_view, Component...> view(exclude_t = {}) { static_assert(sizeof...(Component) > 0, "Exclusion-only views are not supported"); - return { assure>()..., assure()... }; + return { *assure>()..., *assure()... }; } /** @@ -1189,7 +1195,7 @@ public: using handler_type = group_handler, get_t...>, std::decay_t...>; - const auto cpools = std::forward_as_tuple(assure>()..., assure>()...); + const auto cpools = std::make_tuple(assure>()..., assure>()...); constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude); handler_type *handler = nullptr; @@ -1253,17 +1259,13 @@ public: } } else { // we cannot iterate backwards because we want to leave behind valid entities in case of owned types - for(auto *first = std::get<0>(cpools).data(), *last = first + std::get<0>(cpools).size(); first != last; ++first) { + for(auto *first = std::get<0>(cpools)->data(), *last = first + std::get<0>(cpools)->size(); first != last; ++first) { handler->template maybe_valid_if...>>>(*this, *first); } } } - if constexpr(sizeof...(Owned) == 0) { - return { handler->current, std::get> &>(cpools)... }; - } else { - return { handler->current, std::get> &>(cpools)... , std::get> &>(cpools)... }; - } + return { handler->current, *std::get> *>(cpools)..., *std::get> *>(cpools)... }; } /** @@ -1279,7 +1281,19 @@ public: template [[nodiscard]] basic_group, get_t, Owned...> group(get_t, exclude_t = {}) const { static_assert(std::conjunction_v..., std::is_const...>, "Invalid non-const type"); - return const_cast(this)->group(get_t{}, exclude); + + if(auto it = std::find_if(groups.cbegin(), groups.cend(), [](const auto &gdata) { + return gdata.size == (sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude)) + && (gdata.owned(type_hash>::value()) && ...) + && (gdata.get(type_hash>::value()) && ...) + && (gdata.exclude(type_hash::value()) && ...); + }); it == groups.cend()) + { + return {}; + } else { + using handler_type = group_handler, get_t...>, std::decay_t...>; + return { static_cast(it->group.get())->current, *assure>()... , *assure>()... }; + } } /** @@ -1307,8 +1321,7 @@ public: */ template [[nodiscard]] basic_group, get_t<>, Owned...> group(exclude_t = {}) const { - static_assert(std::conjunction_v...>, "Invalid non-const type"); - return const_cast(this)->group(exclude); + return group(get_t<>{}, exclude); } /** @@ -1385,7 +1398,7 @@ public: template void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { ENTT_ASSERT(sortable()); - assure().sort(std::move(compare), std::move(algo), std::forward(args)...); + assure()->sort(std::move(compare), std::move(algo), std::forward(args)...); } /** @@ -1424,7 +1437,7 @@ public: template void sort() { ENTT_ASSERT(sortable()); - assure().respect(assure()); + assure()->respect(*assure()); } /** @@ -1602,8 +1615,8 @@ public: } private: + std::vector pools{}; std::vector groups{}; - mutable std::vector pools{}; std::vector entities{}; std::vector vars{}; entity_type available{null};