Просмотр исходного кода

any:
* ::type() returns the object type if any, type_id<void>() otherwise
* avoid indirection when accessing the type

Michele Caini 4 лет назад
Родитель
Сommit
83853c3dee

+ 17 - 15
src/entt/core/any.hpp

@@ -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());
     }

+ 2 - 2
src/entt/poly/poly.hpp

@@ -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();

+ 13 - 13
test/entt/core/any.cpp

@@ -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) {

+ 2 - 2
test/entt/poly/poly_deduced.cpp

@@ -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) {

+ 2 - 2
test/entt/poly/poly_defined.cpp

@@ -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) {