Przeglądaj źródła

meta: context aware copy/move ctor for meta_any

Michele Caini 3 lat temu
rodzic
commit
11c1e23a91
4 zmienionych plików z 59 dodań i 1 usunięć
  1. 1 0
      TODO
  2. 23 1
      src/entt/meta/meta.hpp
  3. 2 0
      src/entt/meta/node.hpp
  4. 33 0
      test/entt/meta/meta_utility.cpp

+ 1 - 0
TODO

@@ -12,6 +12,7 @@ DOC:
 * update entity doc when the storage based model is in place
 
 TODO (high prio):
+* remove_const_t vs remove_cv_t
 * remove the static storage from the const assure in the registry
 
 WIP:

+ 23 - 1
src/entt/meta/meta.hpp

@@ -259,10 +259,32 @@ public:
      * @param area The context from which to search for meta types.
      * @param value An instance of an object to use to initialize the wrapper.
      */
-    template<typename Type>
+    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
     meta_any(const meta_ctx &area, Type &&value)
         : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
 
+    /**
+     * @brief Context aware copy constructor.
+     * @param area The context from which to search for meta types.
+     * @param other The instance to copy from.
+     */
+    meta_any(const meta_ctx &area, const meta_any &other)
+        : meta_any{other} {
+        ctx = &area;
+        node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node;
+    }
+
+    /**
+     * @brief Context aware move constructor.
+     * @param area The context from which to search for meta types.
+     * @param other The instance to move from.
+     */
+    meta_any(const meta_ctx &area, meta_any &&other)
+        : meta_any{std::move(other)} {
+        ctx = &area;
+        node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node;
+    }
+
     /**
      * @brief Copy constructor.
      * @param other The instance to copy from.

+ 2 - 0
src/entt/meta/node.hpp

@@ -121,6 +121,7 @@ struct meta_type_node {
     id_type id{};
     meta_traits traits{meta_traits::is_none};
     size_type size_of{0u};
+    meta_type_node (*resolve)(const meta_context &) noexcept {};
     meta_type_node (*remove_pointer)(const meta_context &) noexcept {};
     meta_any (*default_constructor)(const meta_ctx &){};
     double (*conversion_helper)(void *, const void *){};
@@ -184,6 +185,7 @@ template<typename Type>
             | (is_complete_v<meta_sequence_container_traits<Type>> ? meta_traits::is_meta_sequence_container : meta_traits::is_none)
             | (is_complete_v<meta_associative_container_traits<Type>> ? meta_traits::is_meta_associative_container : meta_traits::is_none),
         size_of_v<Type>,
+        &resolve<Type>,
         &resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>};
 
     if constexpr(std::is_default_constructible_v<Type>) {

+ 33 - 0
test/entt/meta/meta_utility.cpp

@@ -77,6 +77,39 @@ TEST_F(MetaUtility, MetaDispatch) {
     ASSERT_EQ(as_cref.cast<int>(), 42);
 }
 
+TEST_F(MetaUtility, MetaDispatchMetaAny) {
+    entt::meta_any any{42};
+
+    auto from_any = entt::meta_dispatch(any);
+    auto from_const_any = entt::meta_dispatch(std::as_const(any));
+
+    ASSERT_EQ(from_any.type(), entt::resolve<int>());
+    ASSERT_EQ(from_const_any.type(), entt::resolve<int>());
+
+    ASSERT_NE(from_any.try_cast<int>(), nullptr);
+    ASSERT_NE(from_const_any.try_cast<int>(), nullptr);
+
+    ASSERT_EQ(from_any.cast<int>(), 42);
+    ASSERT_EQ(from_const_any.cast<int>(), 42);
+}
+
+TEST_F(MetaUtility, MetaDispatchMetaAnyAsRef) {
+    entt::meta_any any{42};
+
+    auto from_any = entt::meta_dispatch(any.as_ref());
+    auto from_const_any = entt::meta_dispatch(std::as_const(any).as_ref());
+
+    ASSERT_EQ(from_any.type(), entt::resolve<int>());
+    ASSERT_EQ(from_const_any.type(), entt::resolve<int>());
+
+    ASSERT_NE(from_any.try_cast<int>(), nullptr);
+    ASSERT_EQ(from_const_any.try_cast<int>(), nullptr);
+    ASSERT_NE(from_const_any.try_cast<const int>(), nullptr);
+
+    ASSERT_EQ(from_any.cast<int>(), 42);
+    ASSERT_EQ(from_const_any.cast<int>(), 42);
+}
+
 TEST_F(MetaUtility, MetaArg) {
     ASSERT_EQ((entt::meta_arg<entt::type_list<int, char>>(0u)), entt::resolve<int>());
     ASSERT_EQ((entt::meta_arg<entt::type_list<int, char>>(1u)), entt::resolve<char>());