Browse Source

meta: review meta_base_node::cast and meta_any::try_cast to reduce their sizes

Michele Caini 3 years ago
parent
commit
ab859f7fa7
3 changed files with 33 additions and 36 deletions
  1. 2 6
      src/entt/meta/factory.hpp
  2. 14 29
      src/entt/meta/meta.hpp
  3. 17 1
      src/entt/meta/node.hpp

+ 2 - 6
src/entt/meta/factory.hpp

@@ -202,12 +202,8 @@ public:
 
         internal::meta_base_node node{
             &internal::resolve<Base>,
-            +[](meta_any other) noexcept {
-                if(auto *ptr = other.data(); ptr) {
-                    return forward_as_meta(*static_cast<Base *>(static_cast<Type *>(ptr)));
-                }
-
-                return forward_as_meta(*static_cast<const Base *>(static_cast<const Type *>(std::as_const(other).data())));
+            +[](const void *instance) noexcept {
+                return static_cast<const void *>(static_cast<const Base *>(static_cast<const Type *>(instance)));
             }};
 
         internal::meta_extend(owner(), type_id<Base>().hash(), std::move(node));

+ 14 - 29
src/entt/meta/meta.hpp

@@ -341,30 +341,17 @@ public:
      */
     template<typename Type>
     [[nodiscard]] const Type *try_cast() const {
-        auto *self = any_cast<Type>(&storage);
-
-        if(!self && node.details) {
-            for(auto it = node.details->base.cbegin(), last = node.details->base.cend(); it != last && !self; ++it) {
-                const auto &as_const = it->second.cast(as_ref());
-                self = as_const.template try_cast<Type>();
-            }
-        }
-
-        return self;
+        return static_cast<const Type *>(internal::try_cast(node, internal::resolve<std::remove_cv_t<Type>>(), data()));
     }
 
     /*! @copydoc try_cast */
     template<typename Type>
     [[nodiscard]] Type *try_cast() {
-        auto *self = any_cast<Type>(&storage);
-
-        if(!self && node.details) {
-            for(auto it = node.details->base.cbegin(), last = node.details->base.cend(); it != last && !self; ++it) {
-                self = it->second.cast(as_ref()).template try_cast<Type>();
-            }
+        if constexpr(std::is_const_v<Type>) {
+            return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
+        } else {
+            return static_cast<Type *>(const_cast<void *>(internal::try_cast(node, internal::resolve<Type>(), data())));
         }
-
-        return self;
     }
 
     /**
@@ -1447,7 +1434,15 @@ bool meta_any::set(const id_type id, Type &&value) {
         return as_ref();
     }
 
-    if(node.details) {
+    if(const auto *value = data(); node.details) {
+        for(auto &&curr: node.details->base) {
+            const auto &as_const = curr.second.type().from_void(nullptr, curr.second.cast(value));
+
+            if(auto other = as_const.allow_cast(type); other) {
+                return other;
+            }
+        }
+
         if(auto it = node.details->conv.find(type.info().hash()); it != node.details->conv.cend()) {
             return it->second.conv(data());
         }
@@ -1462,16 +1457,6 @@ bool meta_any::set(const id_type id, Type &&value) {
         return other;
     }
 
-    if(node.details) {
-        for(auto &&curr: node.details->base) {
-            const auto &as_const = curr.second.cast(as_ref());
-
-            if(auto other = as_const.allow_cast(type); other) {
-                return other;
-            }
-        }
-    }
-
     return {};
 }
 

+ 17 - 1
src/entt/meta/node.hpp

@@ -58,7 +58,7 @@ struct meta_prop_map {
 
 struct meta_base_node {
     meta_type_node (*type)() noexcept {};
-    meta_any (*cast)(meta_any) noexcept {};
+    const void *(*cast)(const void *) noexcept {};
 };
 
 struct meta_conv_node {
@@ -154,6 +154,22 @@ template<typename... Args>
     return it != context.value.end() ? &it->second : nullptr;
 }
 
+[[nodiscard]] inline const void *try_cast(const meta_type_node &from, const meta_type_node &to, const void *instance) noexcept {
+    if(from.info && to.info && *from.info == *to.info) {
+        return instance;
+    }
+
+    if(from.details) {
+        for(auto &&curr: from.details->base) {
+            if(const void *elem = try_cast(curr.second.type(), to, curr.second.cast(instance)); elem) {
+                return elem;
+            }
+        }
+    }
+
+    return nullptr;
+}
+
 template<typename Type>
 [[nodiscard]] meta_type_node resolve() noexcept {
     static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");