any: skip vtable on move for reference types

This commit is contained in:
Michele Caini
2024-10-25 09:20:30 +02:00
parent 6405aece3a
commit e13c87a447
2 changed files with 19 additions and 11 deletions

1
TODO
View File

@@ -42,3 +42,4 @@ TODO:
* sigh_mixin: change cb signature from reg/entt to storage/entt (breaking for the good) * sigh_mixin: change cb signature from reg/entt to storage/entt (breaking for the good)
* don't pass reactive storage by default to callback * don't pass reactive storage by default to callback
* runtime types support for meta for types that aren't backed by C++ types * runtime types support for meta for types that aren't backed by C++ types
* bypass vtable in any (improvements available for move/get, add more policy types)

View File

@@ -75,13 +75,13 @@ class basic_any {
} }
break; break;
case operation::move: case operation::move:
if constexpr(in_situ<Type>) { ENTT_ASSERT(value.mode == any_policy::owner, "Unexpected mode");
if(value.mode == any_policy::owner) {
return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(elem))};
}
}
return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr)); if constexpr(in_situ<Type>) {
return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(elem))};
} else {
return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr));
}
case operation::transfer: case operation::transfer:
if constexpr(std::is_move_assignable_v<Type>) { if constexpr(std::is_move_assignable_v<Type>) {
*const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other))); *const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other)));
@@ -208,7 +208,10 @@ public:
info{other.info}, info{other.info},
vtable{other.vtable}, vtable{other.vtable},
mode{other.mode} { mode{other.mode} {
if(other.vtable) { if(other.mode != any_policy::owner) {
ENTT_ASSERT(other.mode == any_policy::ref || other.mode == any_policy::cref, "Unexpected mode");
instance = std::exchange(other.instance, nullptr);
} else if(other.vtable) {
other.vtable(operation::move, other, this); other.vtable(operation::move, other, this);
} }
} }
@@ -247,13 +250,17 @@ public:
reset(); reset();
if(other.vtable) { if(other.mode != any_policy::owner) {
ENTT_ASSERT(other.mode == any_policy::ref || other.mode == any_policy::cref, "Unexpected mode");
instance = std::exchange(other.instance, nullptr);
} else if(other.vtable) {
other.vtable(operation::move, other, this); other.vtable(operation::move, other, this);
info = other.info;
vtable = other.vtable;
mode = other.mode;
} }
info = other.info;
vtable = other.vtable;
mode = other.mode;
return *this; return *this;
} }