* ::type() returns the object type if any, type_id<void>() otherwise
* avoid indirection when accessing the type
This commit is contained in:
Michele Caini
2021-09-09 14:00:08 +02:00
parent 8a0343ad6b
commit 83853c3dee
5 changed files with 36 additions and 34 deletions

View File

@@ -23,7 +23,7 @@ namespace entt {
*/
template<std::size_t Len, std::size_t Align>
class basic_any {
enum class operation: std::uint8_t { COPY, MOVE, DTOR, COMP, ADDR, TYPE };
enum class operation: std::uint8_t { COPY, MOVE, DTOR, COMP, ADDR };
enum class policy: std::uint8_t { OWNER, REF, CREF };
using storage_type = std::aligned_storage_t<Len + !Len, Align>;
@@ -90,9 +90,6 @@ class basic_any {
return compare<Type>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
case operation::ADDR:
return instance;
case operation::TYPE:
*static_cast<type_info *>(to) = type_id<Type>();
break;
}
}
@@ -130,6 +127,7 @@ class basic_any {
basic_any(const basic_any &other, const policy pol) ENTT_NOEXCEPT
: instance{other.data()},
vtable{other.vtable},
descriptor{other.descriptor},
mode{pol}
{}
@@ -143,6 +141,7 @@ public:
basic_any() ENTT_NOEXCEPT
: instance{},
vtable{&basic_vtable<void>},
descriptor{type_id<void>()},
mode{policy::OWNER}
{}
@@ -156,6 +155,7 @@ public:
explicit basic_any(std::in_place_type_t<Type>, Args &&... args)
: instance{},
vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>},
descriptor{type_id<std::remove_const_t<std::remove_reference_t<Type>>>()},
mode{type_to_policy<Type>()}
{
initialize<Type>(std::forward<Args>(args)...);
@@ -170,6 +170,7 @@ public:
basic_any(Type &&value)
: instance{},
vtable{&basic_vtable<std::decay_t<Type>>},
descriptor{type_id<std::decay_t<Type>>()},
mode{policy::OWNER}
{
initialize<std::decay_t<Type>>(std::forward<Type>(value));
@@ -180,9 +181,7 @@ public:
* @param other The instance to copy from.
*/
basic_any(const basic_any &other)
: instance{},
vtable{&basic_vtable<void>},
mode{policy::OWNER}
: basic_any{}
{
other.vtable(operation::COPY, other, this);
}
@@ -194,6 +193,7 @@ public:
basic_any(basic_any &&other) ENTT_NOEXCEPT
: instance{},
vtable{other.vtable},
descriptor{other.descriptor},
mode{other.mode}
{
vtable(operation::MOVE, other, this);
@@ -224,6 +224,7 @@ public:
destroy_if_owner();
other.vtable(operation::MOVE, other, this);
vtable = other.vtable;
descriptor = other.descriptor;
mode = other.mode;
return *this;
}
@@ -242,13 +243,11 @@ public:
}
/**
* @brief Returns the type of the contained object.
* @return The type of the contained object, if any.
* @brief Returns the object type if any, `type_id<void>()` otherwise.
* @return The object type if any, `type_id<void>()` otherwise.
*/
[[nodiscard]] type_info type() const ENTT_NOEXCEPT {
type_info info{};
vtable(operation::TYPE, *this, &info);
return info;
return descriptor;
}
/**
@@ -275,6 +274,7 @@ public:
destroy_if_owner();
initialize<Type>(std::forward<Args>(args)...);
vtable = &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>;
descriptor = type_id<Type>();
mode = type_to_policy<Type>();
}
@@ -282,6 +282,7 @@ public:
void reset() {
destroy_if_owner();
vtable = &basic_vtable<void>;
descriptor = type_id<void>();
mode = policy::OWNER;
}
@@ -300,7 +301,7 @@ public:
*/
bool operator==(const basic_any &other) const ENTT_NOEXCEPT {
const basic_any *trampoline = &other;
return type() == other.type() && (vtable(operation::COMP, *this, &trampoline) || !other.data());
return descriptor == other.descriptor && (vtable(operation::COMP, *this, &trampoline) || !other.data());
}
/**
@@ -327,6 +328,7 @@ public:
private:
union { const void *instance; storage_type storage; };
vtable_type *vtable;
type_info descriptor;
policy mode;
};
@@ -391,7 +393,7 @@ Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
/*! @copydoc any_cast */
template<typename Type, std::size_t Len, std::size_t Align>
const Type * any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
if(const auto hash = type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value(); hash == data->type().hash_code()) {
if(constexpr auto hash = type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value(); hash == data->type().hash_code()) {
return static_cast<const Type *>(data->data());
}
@@ -402,7 +404,7 @@ const Type * any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
/*! @copydoc any_cast */
template<typename Type, std::size_t Len, std::size_t Align>
Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
if(const auto hash = type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value(); hash == data->type().hash_code()) {
if(constexpr auto hash = type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value(); hash == data->type().hash_code()) {
// last attempt to make wrappers for const references return their values
return static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data());
}

View File

@@ -235,8 +235,8 @@ public:
{}
/**
* @brief Returns the type of the contained object.
* @return The type of the contained object, if any.
* @brief Returns the object type if any, `type_id<void>()` otherwise.
* @return The object type if any, `type_id<void>()` otherwise.
*/
[[nodiscard]] type_info type() const ENTT_NOEXCEPT {
return storage.type();

View File

@@ -75,7 +75,7 @@ TEST_F(Any, Empty) {
ASSERT_FALSE(any);
ASSERT_TRUE(any.owner());
ASSERT_FALSE(any.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(any.data(), nullptr);
}
@@ -417,7 +417,7 @@ TEST_F(Any, VoidInPlaceTypeConstruction) {
ASSERT_FALSE(any);
ASSERT_TRUE(any.owner());
ASSERT_FALSE(any.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
}
@@ -429,8 +429,8 @@ TEST_F(Any, VoidCopyConstruction) {
ASSERT_FALSE(other);
ASSERT_TRUE(any.owner());
ASSERT_TRUE(other.owner());
ASSERT_FALSE(any.type());
ASSERT_FALSE(other.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(other.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
}
@@ -445,8 +445,8 @@ TEST_F(Any, VoidCopyAssignment) {
ASSERT_FALSE(other);
ASSERT_TRUE(any.owner());
ASSERT_TRUE(other.owner());
ASSERT_FALSE(any.type());
ASSERT_FALSE(other.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(other.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
}
@@ -459,8 +459,8 @@ TEST_F(Any, VoidMoveConstruction) {
ASSERT_FALSE(other);
ASSERT_TRUE(any.owner());
ASSERT_TRUE(other.owner());
ASSERT_FALSE(any.type());
ASSERT_FALSE(other.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(other.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
}
@@ -475,8 +475,8 @@ TEST_F(Any, VoidMoveAssignment) {
ASSERT_FALSE(other);
ASSERT_TRUE(any.owner());
ASSERT_TRUE(other.owner());
ASSERT_FALSE(any.type());
ASSERT_FALSE(other.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(other.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
}
@@ -558,7 +558,7 @@ TEST_F(Any, EmplaceVoid) {
ASSERT_FALSE(any);
ASSERT_TRUE(any.owner());
ASSERT_FALSE(any.type());
ASSERT_EQ(any.type(), entt::type_id<void>());
}
TEST_F(Any, Reset) {
@@ -572,7 +572,7 @@ TEST_F(Any, Reset) {
ASSERT_FALSE(any);
ASSERT_TRUE(any.owner());
ASSERT_EQ(any.type(), entt::type_info{});
ASSERT_EQ(any.type(), entt::type_id<void>());
int value = 42;
any.emplace<int &>(value);
@@ -585,7 +585,7 @@ TEST_F(Any, Reset) {
ASSERT_FALSE(any);
ASSERT_TRUE(any.owner());
ASSERT_EQ(any.type(), entt::type_info{});
ASSERT_EQ(any.type(), entt::type_id<void>());
}
TEST_F(Any, SBOSwap) {

View File

@@ -56,7 +56,7 @@ TEST(PolyDeduced, Functionalities) {
ASSERT_TRUE(alias);
ASSERT_TRUE(value);
ASSERT_EQ(empty.type(), entt::type_info{});
ASSERT_EQ(empty.type(), entt::type_id<void>());
ASSERT_EQ(in_place.type(), entt::type_id<impl>());
ASSERT_EQ(alias.type(), entt::type_id<impl>());
ASSERT_EQ(value.type(), entt::type_id<impl>());
@@ -105,7 +105,7 @@ TEST(PolyDeduced, Functionalities) {
move.reset();
ASSERT_FALSE(move);
ASSERT_EQ(move.type(), entt::type_info{});
ASSERT_EQ(move.type(), entt::type_id<void>());
}
TEST(PolyDeduced, Owned) {

View File

@@ -62,7 +62,7 @@ TEST(PolyDefined, Functionalities) {
ASSERT_TRUE(alias);
ASSERT_TRUE(value);
ASSERT_EQ(empty.type(), entt::type_info{});
ASSERT_EQ(empty.type(), entt::type_id<void>());
ASSERT_EQ(in_place.type(), entt::type_id<impl>());
ASSERT_EQ(alias.type(), entt::type_id<impl>());
ASSERT_EQ(value.type(), entt::type_id<impl>());
@@ -111,7 +111,7 @@ TEST(PolyDefined, Functionalities) {
move.reset();
ASSERT_FALSE(move);
ASSERT_EQ(move.type(), entt::type_info{});
ASSERT_EQ(move.type(), entt::type_id<void>());
}
TEST(PolyDefined, Owned) {