any/registry:
* copying an entt::any always returns a copy of the contained object * registry::storage returns references (eventually const) to the poly storage
This commit is contained in:
1
TODO
1
TODO
@@ -18,7 +18,6 @@
|
||||
- ...
|
||||
|
||||
WIP:
|
||||
* HP: registry::ctx can return entt::any objects directly
|
||||
* HP: merge view and view pack
|
||||
* HP: invalid view auto-refresh
|
||||
* HP: paginate pools
|
||||
|
||||
@@ -42,19 +42,22 @@ class any {
|
||||
static const void * basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &from, [[maybe_unused]] const void *to) {
|
||||
if constexpr(!std::is_void_v<Type>) {
|
||||
if constexpr(std::is_lvalue_reference_v<Type>) {
|
||||
using base_type = std::remove_reference_t<Type>;
|
||||
using base_type = std::remove_const_t<std::remove_reference_t<Type>>;
|
||||
|
||||
switch(op) {
|
||||
case operation::COPY:
|
||||
as<any>(to).vtable = from.vtable;
|
||||
if constexpr(std::is_copy_constructible_v<base_type>) {
|
||||
as<any>(to).emplace<base_type>(*static_cast<const base_type *>(from.instance));
|
||||
}
|
||||
break;
|
||||
case operation::MOVE:
|
||||
as<any>(to).instance = from.instance;
|
||||
case operation::DTOR:
|
||||
break;
|
||||
case operation::COMP:
|
||||
return compare<std::remove_const_t<base_type>>(from.instance, to) ? to : nullptr;
|
||||
return compare<base_type>(from.instance, to) ? to : nullptr;
|
||||
case operation::ADDR:
|
||||
return std::is_const_v<base_type> ? nullptr : from.instance;
|
||||
return std::is_const_v<std::remove_reference_t<Type>> ? nullptr : from.instance;
|
||||
case operation::CADDR:
|
||||
return from.instance;
|
||||
case operation::REF:
|
||||
@@ -66,7 +69,7 @@ class any {
|
||||
as<any>(to).instance = from.instance;
|
||||
break;
|
||||
case operation::TYPE:
|
||||
as<type_info>(to) = type_id<std::remove_const_t<base_type>>();
|
||||
as<type_info>(to) = type_id<base_type>();
|
||||
break;
|
||||
}
|
||||
} else if constexpr(in_situ<Type>) {
|
||||
|
||||
@@ -181,14 +181,15 @@ public:
|
||||
* @return A valid poly storage if a pool for the given type exists, an
|
||||
* empty and thus invalid element otherwise.
|
||||
*/
|
||||
poly_storage storage(const type_info info) {
|
||||
return info.seq() < pools.size() ? pools[info.seq()].poly : poly_storage{};
|
||||
poly_storage & storage(const type_info info) {
|
||||
ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly);
|
||||
return pools[info.seq()].poly;
|
||||
}
|
||||
|
||||
/*! @copydoc storage */
|
||||
poly_storage storage(const type_info info) const {
|
||||
// as_ref forces a constness conversion for the underlying pool
|
||||
return info.seq() < pools.size() ? as_ref(pools[info.seq()].poly) : poly_storage{};
|
||||
const poly_storage & storage(const type_info info) const {
|
||||
ENTT_ASSERT(info.seq() < pools.size() && pools[info.seq()].poly);
|
||||
return pools[info.seq()].poly;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -837,3 +837,35 @@ TEST(Any, Array) {
|
||||
|
||||
ASSERT_EQ(entt::any_cast<const int(&)[1]>(std::as_const(any))[0], 42);
|
||||
}
|
||||
|
||||
TEST(Any, CopyMoveReference) {
|
||||
auto test = [](int &value, auto ref) {
|
||||
value = 3;
|
||||
|
||||
entt::any any{ref};
|
||||
entt::any move = std::move(any);
|
||||
entt::any copy = move;
|
||||
|
||||
ASSERT_FALSE(any);
|
||||
ASSERT_TRUE(move);
|
||||
ASSERT_TRUE(copy);
|
||||
|
||||
ASSERT_EQ(move.type(), entt::type_id<int>());
|
||||
ASSERT_EQ(copy.type(), entt::type_id<int>());
|
||||
|
||||
ASSERT_EQ(std::as_const(move).data(), &value);
|
||||
ASSERT_NE(std::as_const(copy).data(), &value);
|
||||
|
||||
ASSERT_EQ(entt::any_cast<int>(move), 3);
|
||||
ASSERT_EQ(entt::any_cast<int>(copy), 3);
|
||||
|
||||
value = 42;
|
||||
|
||||
ASSERT_EQ(entt::any_cast<const int &>(move), 42);
|
||||
ASSERT_EQ(entt::any_cast<const int &>(copy), 3);
|
||||
};
|
||||
|
||||
int value{};
|
||||
test(value, std::ref(value));
|
||||
test(value, std::cref(value));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
entt::type_list<
|
||||
void(entt::basic_registry<Entity> &, const Entity, const void *),
|
||||
const void *(const Entity) const,
|
||||
void(entt::basic_registry<Entity> &, entt::basic_registry<Entity> &)
|
||||
void(const entt::basic_registry<Entity> &, entt::basic_registry<Entity> &) const
|
||||
>
|
||||
> {
|
||||
using entity_type = Entity;
|
||||
@@ -31,7 +31,7 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
return entt::poly_call<base + 1>(*this, entity);
|
||||
}
|
||||
|
||||
void copy(entt::basic_registry<Entity> &owner, entt::basic_registry<Entity> &other) {
|
||||
void copy(const entt::basic_registry<Entity> &owner, entt::basic_registry<Entity> &other) const {
|
||||
entt::poly_call<base + 2>(*this, owner, other);
|
||||
}
|
||||
};
|
||||
@@ -46,7 +46,7 @@ struct PolyStorage: entt::type_list_cat_t<
|
||||
return &self.get(entity);
|
||||
}
|
||||
|
||||
static void copy(Type &self, entt::basic_registry<entity_type> &owner, entt::basic_registry<entity_type> &other) {
|
||||
static void copy(const Type &self, const entt::basic_registry<entity_type> &owner, entt::basic_registry<entity_type> &other) {
|
||||
other.template insert<typename Type::value_type>(self.data(), self.data() + self.size(), self.raw(), self.raw() + self.size());
|
||||
}
|
||||
};
|
||||
@@ -79,7 +79,7 @@ TEST(PolyStorage, CopyEntity) {
|
||||
ASSERT_FALSE((registry.any_of<int, char>(other)));
|
||||
|
||||
registry.visit(entity, [&](const auto info) {
|
||||
auto storage = registry.storage(info);
|
||||
auto &&storage = registry.storage(info);
|
||||
storage->emplace(registry, other, storage->get(entity));
|
||||
});
|
||||
|
||||
@@ -103,7 +103,7 @@ TEST(PolyStorage, CopyRegistry) {
|
||||
ASSERT_EQ(other.size(), 0u);
|
||||
|
||||
other.assign(registry.data(), registry.data() + registry.size(), registry.destroyed());
|
||||
registry.visit([&](const auto info) { registry.storage(info)->copy(registry, other); });
|
||||
registry.visit([&](const auto info) { std::as_const(registry).storage(info)->copy(registry, other); });
|
||||
|
||||
ASSERT_EQ(registry.size(), other.size());
|
||||
ASSERT_EQ((registry.view<int, char>().size_hint()), (other.view<int, char>().size_hint()));
|
||||
@@ -122,12 +122,13 @@ TEST(PolyStorage, Constness) {
|
||||
entity[0] = registry.create();
|
||||
registry.emplace<int>(entity[0], 42);
|
||||
|
||||
// cannot invoke remove on a const storage, let's copy the returned value
|
||||
auto cstorage = cregistry.storage(entt::type_id<int>());
|
||||
|
||||
ASSERT_DEATH(cstorage->remove(registry, std::begin(entity), std::end(entity)), ".*");
|
||||
ASSERT_TRUE(registry.all_of<int>(entity[0]));
|
||||
|
||||
auto storage = registry.storage(entt::type_id<int>());
|
||||
auto &&storage = registry.storage(entt::type_id<int>());
|
||||
storage->remove(registry, std::begin(entity), std::end(entity));
|
||||
|
||||
ASSERT_FALSE(registry.all_of<int>(entity[0]));
|
||||
|
||||
Reference in New Issue
Block a user