Browse Source

added meta_any constructor for the unmanaged object taken from a meta_handle

Michele Caini 6 years ago
parent
commit
80b444e531
3 changed files with 62 additions and 31 deletions
  1. 6 6
      src/entt/meta/factory.hpp
  2. 26 8
      src/entt/meta/meta.hpp
  3. 30 17
      test/entt/meta/meta.cpp

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

@@ -91,7 +91,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
             using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
             static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
             auto *direct = value.try_cast<data_type>();
-            auto *clazz = handle.data<Type>();
+            auto *clazz = handle.try_cast<Type>();
 
             if(clazz && (direct || value.convert<data_type>())) {
                 std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
@@ -100,7 +100,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
         } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
             using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
             static_assert(std::is_invocable_v<decltype(Data), Type *>);
-            auto *clazz = handle.data<Type>();
+            auto *clazz = handle.try_cast<Type>();
 
             if constexpr(std::is_array_v<data_type>) {
                 using underlying_type = std::remove_extent_t<data_type>;
@@ -162,12 +162,12 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
 
     if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
         static_assert(std::is_invocable_v<decltype(Data), Type &>);
-        auto *clazz = handle.data<Type>();
+        auto *clazz = handle.try_cast<Type>();
         return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
         static_assert(std::is_invocable_v<decltype(Data), Type *>);
-        auto *clazz = handle.data<Type>();
+        auto *clazz = handle.try_cast<Type>();
 
         if constexpr(std::is_array_v<data_type>) {
             auto *idx = index.try_cast<std::size_t>();
@@ -217,7 +217,7 @@ meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_
     if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Candidate)>>) {
         return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : meta_any{};
     } else {
-        auto *clazz = handle.data<Type>();
+        auto *clazz = handle.try_cast<Type>();
         return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : meta_any{};
     }
 }
@@ -564,7 +564,7 @@ public:
                 const auto valid = (handle.type() == internal::meta_info<Type>::resolve()->meta());
 
                 if(valid) {
-                    std::invoke(Func, *handle.data<Type>());
+                    std::invoke(Func, *handle.try_cast<Type>());
                 }
 
                 return valid;

+ 26 - 8
src/entt/meta/meta.hpp

@@ -15,7 +15,7 @@ namespace entt {
 
 
 class meta_any;
-struct meta_handle;
+class meta_handle;
 class meta_prop;
 class meta_base;
 class meta_conv;
@@ -298,7 +298,7 @@ inline auto ctor(std::index_sequence<Indexes...>, const meta_type_node *node) EN
  */
 class meta_any {
     /*! @brief A meta handle is allowed to _inherit_ from a meta any. */
-    friend struct meta_handle;
+    friend class meta_handle;
 
     using storage_type = std::aligned_storage_t<sizeof(void *), alignof(void *)>;
     using copy_fn_type = void *(storage_type &, const void *);
@@ -406,6 +406,12 @@ public:
         instance = &type.get();
     }
 
+    /**
+     * @brief Constructs a meta any from a meta handle object.
+     * @param handle A reference to an object to use to initialize the meta any.
+     */
+    inline meta_any(meta_handle handle) ENTT_NOEXCEPT;
+
     /**
      * @brief Constructs a meta any from a given value.
      * @tparam Type Type of object to use to initialize the container.
@@ -649,7 +655,7 @@ public:
 private:
     storage_type storage;
     void *instance;
-    internal::meta_type_node *node;
+    const internal::meta_type_node *node;
     destroy_fn_type *destroy_fn;
     copy_fn_type *copy_fn;
     steal_fn_type *steal_fn;
@@ -666,7 +672,11 @@ private:
  * responsible for ensuring that the target object remains alive for the entire
  * interval of use of the handle.
  */
-struct meta_handle {
+class meta_handle {
+    /*! @brief A meta any is allowed to _inherit_ from a meta handle. */
+    friend class meta_any;
+
+public:
     /*! @brief Default constructor. */
     meta_handle() ENTT_NOEXCEPT
         : node{nullptr},
@@ -718,14 +728,14 @@ struct meta_handle {
      * @return A (possibly null) pointer to the underlying object.
      */
     template<typename Type>
-    const Type * data() const ENTT_NOEXCEPT {
+    const Type * try_cast() const ENTT_NOEXCEPT {
         return internal::try_cast<Type>(node, instance);
     }
 
-    /*! @copydoc data */
+    /*! @copydoc try_cast */
     template<typename Type>
-    Type * data() ENTT_NOEXCEPT {
-        return const_cast<Type *>(std::as_const(*this).data<Type>());
+    Type * try_cast() ENTT_NOEXCEPT {
+        return const_cast<Type *>(std::as_const(*this).try_cast<Type>());
     }
 
     /**
@@ -1967,6 +1977,14 @@ inline bool operator!=(const meta_type &lhs, const meta_type &rhs) ENTT_NOEXCEPT
 }
 
 
+inline meta_any::meta_any(meta_handle handle) ENTT_NOEXCEPT
+    : meta_any{}
+{
+    node = handle.node;
+    instance = handle.instance;
+}
+
+
 inline meta_type meta_any::type() const ENTT_NOEXCEPT {
     return node ? node->meta() : meta_type{};
 }

+ 30 - 17
test/entt/meta/meta.cpp

@@ -247,6 +247,22 @@ TEST_F(Meta, Resolve) {
     ASSERT_TRUE(found);
 }
 
+TEST_F(Meta, MetaAnyFromMetaHandle) {
+    int value = 42;
+    entt::meta_handle handle{value};
+    entt::meta_any any{handle};
+    any.cast<int>() = 3;
+
+    ASSERT_TRUE(any);
+    ASSERT_EQ(any.type(), entt::resolve<int>());
+    ASSERT_EQ(any.try_cast<std::size_t>(), nullptr);
+    ASSERT_EQ(any.try_cast<int>(), handle.data());
+    ASSERT_EQ(std::as_const(any).try_cast<int>(), handle.data());
+    ASSERT_EQ(any.data(), handle.data());
+    ASSERT_EQ(std::as_const(any).data(), handle.data());
+    ASSERT_EQ(value, 3);
+}
+
 TEST_F(Meta, MetaAnySBO) {
     entt::meta_any any{'c'};
 
@@ -849,9 +865,9 @@ TEST_F(Meta, MetaHandleFromObject) {
 
     ASSERT_TRUE(handle);
     ASSERT_EQ(handle.type(), entt::resolve<empty_type>());
-    ASSERT_EQ(handle.data<std::size_t>(), nullptr);
-    ASSERT_EQ(handle.data<empty_type>(), &empty);
-    ASSERT_EQ(std::as_const(handle).data<empty_type>(), &empty);
+    ASSERT_EQ(handle.try_cast<std::size_t>(), nullptr);
+    ASSERT_EQ(handle.try_cast<empty_type>(), &empty);
+    ASSERT_EQ(std::as_const(handle).try_cast<empty_type>(), &empty);
     ASSERT_EQ(handle.data(), &empty);
     ASSERT_EQ(std::as_const(handle).data(), &empty);
 }
@@ -862,9 +878,9 @@ TEST_F(Meta, MetaHandleFromMetaAny) {
 
     ASSERT_TRUE(handle);
     ASSERT_EQ(handle.type(), entt::resolve<int>());
-    ASSERT_EQ(handle.data<std::size_t>(), nullptr);
-    ASSERT_EQ(handle.data<int>(), any.data());
-    ASSERT_EQ(std::as_const(handle).data<int>(), any.data());
+    ASSERT_EQ(handle.try_cast<std::size_t>(), nullptr);
+    ASSERT_EQ(handle.try_cast<int>(), any.data());
+    ASSERT_EQ(std::as_const(handle).try_cast<int>(), any.data());
     ASSERT_EQ(handle.data(), any.data());
     ASSERT_EQ(std::as_const(handle).data(), any.data());
 }
@@ -874,26 +890,23 @@ TEST_F(Meta, MetaHandleEmpty) {
 
     ASSERT_FALSE(handle);
     ASSERT_FALSE(handle.type());
-    ASSERT_EQ(handle.data<std::size_t>(), nullptr);
-    ASSERT_EQ(handle.data<empty_type>(), nullptr);
+    ASSERT_EQ(handle.try_cast<std::size_t>(), nullptr);
+    ASSERT_EQ(handle.try_cast<empty_type>(), nullptr);
     ASSERT_EQ(handle.data(), nullptr);
     ASSERT_EQ(std::as_const(handle).data(), nullptr);
 }
 
-TEST_F(Meta, MetaHandleData) {
+TEST_F(Meta, MetaHandleTryCast) {
     derived_type derived{};
-    base_type *base = &derived;
     entt::meta_handle handle{derived};
 
     ASSERT_TRUE(handle);
     ASSERT_EQ(handle.type(), entt::resolve<derived_type>());
-    ASSERT_EQ(handle.data<std::size_t>(), nullptr);
-    ASSERT_EQ(handle.data<base_type>(), base);
-    ASSERT_EQ(handle.data<derived_type>(), &derived);
-    ASSERT_EQ(std::as_const(handle).data<base_type>(), base);
-    ASSERT_EQ(std::as_const(handle).data<derived_type>(), &derived);
-    ASSERT_EQ(handle.data(), &derived);
-    ASSERT_EQ(std::as_const(handle).data(), &derived);
+    ASSERT_EQ(handle.try_cast<void>(), nullptr);
+    ASSERT_NE(handle.try_cast<base_type>(), nullptr);
+    ASSERT_EQ(handle.try_cast<derived_type>(), handle.data());
+    ASSERT_EQ(std::as_const(handle).try_cast<base_type>(), handle.try_cast<base_type>());
+    ASSERT_EQ(std::as_const(handle).try_cast<derived_type>(), handle.data());
 }
 
 TEST_F(Meta, MetaProp) {