Parcourir la source

meta: forward_as_meta

Michele Caini il y a 4 ans
Parent
commit
2b5c393a13

+ 12 - 0
src/entt/meta/meta.hpp

@@ -636,6 +636,18 @@ meta_any make_meta(Args &&... args) {
 }
 
 
+/**
+ * @brief Forwards its argument and avoids copies for lvalue references.
+ * @tparam Type Type of argument to use to construct the new instance.
+ * @param value Parameter to use to construct the instance.
+ * @return A properly initialized and not necessarily owning wrapper.
+ */
+template<typename Type>
+meta_any forward_as_meta(Type &&value) {
+    return meta_any{std::in_place_type<std::conditional_t<std::is_rvalue_reference_v<Type>, std::decay_t<Type>, Type>>, std::forward<Type>(value)};
+}
+
+
 /**
  * @brief Opaque pointers to instances of any type.
  *

+ 37 - 15
test/entt/meta/meta_any.cpp

@@ -147,7 +147,7 @@ TEST_F(MetaAny, SBOInPlaceTypeConstruction) {
 TEST_F(MetaAny, SBOAsRefConstruction) {
     int value = 3;
     int compare = 42;
-    auto any = entt::make_meta<int &>(value);
+    auto any = entt::forward_as_meta(value);
 
     ASSERT_TRUE(any);
     ASSERT_EQ(any.type(), entt::resolve<int>());
@@ -159,8 +159,8 @@ TEST_F(MetaAny, SBOAsRefConstruction) {
     ASSERT_EQ(any.data(), &value);
     ASSERT_EQ(std::as_const(any).data(), &value);
 
-    ASSERT_EQ(any, entt::make_meta<int &>(value));
-    ASSERT_NE(any, entt::make_meta<int &>(compare));
+    ASSERT_EQ(any, entt::forward_as_meta(value));
+    ASSERT_NE(any, entt::forward_as_meta(compare));
 
     ASSERT_NE(any, entt::meta_any{42});
     ASSERT_EQ(entt::meta_any{3}, any);
@@ -180,9 +180,9 @@ TEST_F(MetaAny, SBOAsRefConstruction) {
 }
 
 TEST_F(MetaAny, SBOAsConstRefConstruction) {
-    int value = 3;
+    const int value = 3;
     int compare = 42;
-    auto any = entt::make_meta<const int &>(value);
+    auto any = entt::forward_as_meta(value);
 
     ASSERT_TRUE(any);
     ASSERT_EQ(any.type(), entt::resolve<int>());
@@ -194,8 +194,8 @@ TEST_F(MetaAny, SBOAsConstRefConstruction) {
     ASSERT_EQ(any.data(), nullptr);
     ASSERT_EQ(std::as_const(any).data(), &value);
 
-    ASSERT_EQ(any, entt::make_meta<const int &>(value));
-    ASSERT_NE(any, entt::make_meta<const int &>(compare));
+    ASSERT_EQ(any, entt::forward_as_meta(value));
+    ASSERT_NE(any, entt::forward_as_meta(compare));
 
     ASSERT_NE(any, entt::meta_any{42});
     ASSERT_EQ(entt::meta_any{3}, any);
@@ -291,7 +291,7 @@ TEST_F(MetaAny, NoSBOInPlaceTypeConstruction) {
 
 TEST_F(MetaAny, NoSBOAsRefConstruction) {
     fat_t instance{.1, .2, .3, .4};
-    auto any = entt::make_meta<fat_t &>(instance);
+    auto any = entt::forward_as_meta(instance);
 
     ASSERT_TRUE(any);
     ASSERT_EQ(any.type(), entt::resolve<fat_t>());
@@ -303,7 +303,7 @@ TEST_F(MetaAny, NoSBOAsRefConstruction) {
     ASSERT_EQ(any.data(), &instance);
     ASSERT_EQ(std::as_const(any).data(), &instance);
 
-    ASSERT_EQ(any, entt::make_meta<fat_t &>(instance));
+    ASSERT_EQ(any, entt::forward_as_meta(instance));
 
     ASSERT_EQ(any, entt::meta_any{instance});
     ASSERT_NE(entt::meta_any{fat_t{}}, any);
@@ -323,8 +323,8 @@ TEST_F(MetaAny, NoSBOAsRefConstruction) {
 }
 
 TEST_F(MetaAny, NoSBOAsConstRefConstruction) {
-    fat_t instance{.1, .2, .3, .4};
-    auto any = entt::make_meta<const fat_t &>(instance);
+    const fat_t instance{.1, .2, .3, .4};
+    auto any = entt::forward_as_meta(instance);
 
     ASSERT_TRUE(any);
     ASSERT_EQ(any.type(), entt::resolve<fat_t>());
@@ -336,7 +336,7 @@ TEST_F(MetaAny, NoSBOAsConstRefConstruction) {
     ASSERT_EQ(any.data(), nullptr);
     ASSERT_EQ(std::as_const(any).data(), &instance);
 
-    ASSERT_EQ(any, entt::make_meta<const fat_t &>(instance));
+    ASSERT_EQ(any, entt::forward_as_meta(instance));
 
     ASSERT_EQ(any, entt::meta_any{instance});
     ASSERT_NE(entt::meta_any{fat_t{}}, any);
@@ -852,7 +852,7 @@ TEST_F(MetaAny, ConstConvert) {
 
 TEST_F(MetaAny, UnmanageableType) {
     unmanageable_t instance;
-    auto any = entt::make_meta<unmanageable_t &>(instance);
+    auto any = entt::forward_as_meta(instance);
     entt::meta_any other = any.as_ref();
 
     std::swap(any, other);
@@ -876,7 +876,7 @@ TEST_F(MetaAny, Invoke) {
     using namespace entt::literals;
 
     clazz_t instance;
-    auto any = entt::make_meta<clazz_t &>(instance);
+    auto any = entt::forward_as_meta(instance);
 
     ASSERT_TRUE(any.invoke("func"_hs));
     ASSERT_TRUE(any.invoke("member"_hs, 42));
@@ -892,7 +892,7 @@ TEST_F(MetaAny, SetGet) {
     using namespace entt::literals;
 
     clazz_t instance;
-    auto any = entt::make_meta<clazz_t &>(instance);
+    auto any = entt::forward_as_meta(instance);
 
     ASSERT_TRUE(any.set("value"_hs, 42));
 
@@ -923,3 +923,25 @@ TEST_F(MetaAny, MakeMeta) {
     ASSERT_NE(any.data(), &value);
     ASSERT_EQ(ref.data(), &value);
 }
+
+TEST_F(MetaAny, ForwardAsMeta) {
+    int value = 42;
+    auto any = entt::forward_as_meta(std::move(value));
+    auto ref = entt::forward_as_meta(value);
+    auto cref = entt::forward_as_meta(std::as_const(value));
+
+    ASSERT_TRUE(any);
+    ASSERT_TRUE(ref);
+    ASSERT_TRUE(cref);
+
+    ASSERT_NE(any.try_cast<int>(), nullptr);
+    ASSERT_NE(ref.try_cast<int>(), nullptr);
+    ASSERT_EQ(cref.try_cast<int>(), nullptr);
+
+    ASSERT_EQ(any.cast<const int &>(), 42);
+    ASSERT_EQ(ref.cast<const int &>(), 42);
+    ASSERT_EQ(cref.cast<const int &>(), 42);
+
+    ASSERT_NE(any.data(), &value);
+    ASSERT_EQ(ref.data(), &value);
+}

+ 16 - 16
test/entt/meta/meta_container.cpp

@@ -57,7 +57,7 @@ TEST_F(MetaContainer, EmptyAssociativeContainer) {
 
 TEST_F(MetaContainer, SequenceContainerIterator) {
     std::vector<int> vec{2, 3, 4};
-    auto any = entt::make_meta<std::vector<int> &>(vec);
+    auto any = entt::forward_as_meta(vec);
     entt::meta_sequence_container::iterator first{};
     auto view = any.as_sequence_container();
 
@@ -84,7 +84,7 @@ TEST_F(MetaContainer, SequenceContainerIterator) {
 
 TEST_F(MetaContainer, AssociativeContainerIterator) {
     std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
-    auto any = entt::make_meta<std::map<int, char> &>(map);
+    auto any = entt::forward_as_meta(map);
     entt::meta_associative_container::iterator first{};
     auto view = any.as_associative_container();
 
@@ -111,7 +111,7 @@ TEST_F(MetaContainer, AssociativeContainerIterator) {
 
 TEST_F(MetaContainer, StdVector) {
     std::vector<int> vec{};
-    auto any = entt::make_meta<std::vector<int> &>(vec);
+    auto any = entt::forward_as_meta(vec);
 
     auto view = any.as_sequence_container();
 
@@ -154,7 +154,7 @@ TEST_F(MetaContainer, StdVector) {
 
 TEST_F(MetaContainer, StdArray) {
     std::array<int, 3> arr{};
-    auto any = entt::make_meta<std::array<int, 3> &>(arr);
+    auto any = entt::forward_as_meta(arr);
 
     auto view = any.as_sequence_container();
 
@@ -196,7 +196,7 @@ TEST_F(MetaContainer, StdArray) {
 
 TEST_F(MetaContainer, StdMap) {
     std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
-    auto any = entt::make_meta<std::map<int, char> &>(map);
+    auto any = entt::forward_as_meta(map);
 
     auto view = any.as_associative_container();
 
@@ -240,7 +240,7 @@ TEST_F(MetaContainer, StdMap) {
 
 TEST_F(MetaContainer, StdSet) {
     std::set<int> set{2, 3, 4};
-    auto any = entt::make_meta<std::set<int> &>(set);
+    auto any = entt::forward_as_meta(set);
 
     auto view = any.as_associative_container();
 
@@ -283,7 +283,7 @@ TEST_F(MetaContainer, StdSet) {
 
 TEST_F(MetaContainer, ConstSequenceContainer) {
     std::vector<int> vec{};
-    auto any = entt::make_meta<const std::vector<int> &>(vec);
+    auto any = entt::forward_as_meta(std::as_const(vec));
 
     auto view = any.as_sequence_container();
 
@@ -324,7 +324,7 @@ TEST_F(MetaContainer, ConstSequenceContainer) {
 
 TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
     std::map<int, char> map{};
-    auto any = entt::make_meta<const std::map<int, char> &>(map);
+    auto any = entt::forward_as_meta(std::as_const(map));
 
     auto view = any.as_associative_container();
 
@@ -360,7 +360,7 @@ TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
 
 TEST_F(MetaContainer, ConstKeyOnlyAssociativeContainer) {
     std::set<int> set{};
-    auto any = entt::make_meta<const std::set<int> &>(set);
+    auto any = entt::forward_as_meta(std::as_const(set));
 
     auto view = any.as_associative_container();
 
@@ -409,8 +409,8 @@ TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
     std::vector<int> vec{42};
 
     test(vec);
-    test(entt::make_meta<std::vector<int> &>(vec));
-    test(entt::make_meta<const std::vector<int> &>(vec));
+    test(entt::forward_as_meta(vec));
+    test(entt::forward_as_meta(std::as_const(vec)));
 }
 
 TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
@@ -426,8 +426,8 @@ TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
     std::map<int, char> map{{2, 'c'}};
 
     test(map);
-    test(entt::make_meta<std::map<int, char> &>(map));
-    test(entt::make_meta<const std::map<int, char> &>(map));
+    test(entt::forward_as_meta(map));
+    test(entt::forward_as_meta(std::as_const(map)));
 }
 
 TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
@@ -446,8 +446,8 @@ TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
     std::set<int> set{2};
 
     test(set);
-    test(entt::make_meta<std::set<int> &>(set));
-    test(entt::make_meta<const std::set<int> &>(set));
+    test(entt::forward_as_meta(set));
+    test(entt::forward_as_meta(std::as_const(set)));
 }
 
 TEST_F(MetaContainer, StdVectorBool) {
@@ -455,7 +455,7 @@ TEST_F(MetaContainer, StdVectorBool) {
     using const_proxy_type = typename std::vector<bool>::const_reference;
 
     std::vector<bool> vec{};
-    auto any = entt::make_meta<std::vector<bool> &>(vec);
+    auto any = entt::forward_as_meta(vec);
     auto cany = std::as_const(any).as_ref();
 
     auto view = any.as_sequence_container();

+ 4 - 4
test/entt/meta/meta_ctor.cpp

@@ -153,9 +153,9 @@ TEST_F(MetaCtor, CastAndConvert) {
 
 TEST_F(MetaCtor, ConstNonConstRefArgs) {
     int ivalue = 42;
-    char cvalue = 'c';
+    const char cvalue = 'c';
 
-    auto any = entt::resolve<clazz_t>().ctor<int, char>().invoke(entt::make_meta<int &>(ivalue), entt::make_meta<const char &>(cvalue));
+    auto any = entt::resolve<clazz_t>().ctor<int, char>().invoke(entt::forward_as_meta(ivalue), entt::forward_as_meta(cvalue));
 
     ASSERT_TRUE(any);
     ASSERT_EQ(any.cast<clazz_t>().i, 42);
@@ -187,7 +187,7 @@ TEST_F(MetaCtor, FuncConstNonConstRefArgs) {
     int ivalue = 42;
     auto ctor = entt::resolve<clazz_t>().ctor<int>();
 
-    auto any = ctor.invoke(entt::make_meta<int &>(ivalue));
+    auto any = ctor.invoke(entt::forward_as_meta(ivalue));
     auto other = ctor.invoke(entt::make_meta<const int &>(ivalue));
 
     ASSERT_TRUE(any);
@@ -215,7 +215,7 @@ TEST_F(MetaCtor, ExternalMemberFunction) {
 
     ASSERT_FALSE(registry.all_of<clazz_t>(entity));
 
-    const auto any = ctor.invoke(entt::make_meta<entt::registry &>(registry), entity, 3, 'c');
+    const auto any = ctor.invoke(entt::forward_as_meta(registry), entity, 3, 'c');
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(registry.all_of<clazz_t>(entity));

+ 1 - 1
test/entt/meta/meta_dtor.cpp

@@ -74,7 +74,7 @@ TEST_F(MetaDtor, AsRefConstruction) {
     ASSERT_EQ(clazz_t::counter, 0);
 
     clazz_t instance{};
-    auto any = entt::make_meta<clazz_t &>(instance);
+    auto any = entt::forward_as_meta(instance);
     auto cany = entt::make_meta<const clazz_t &>(instance);
     auto cref = cany.as_ref();
     auto ref = any.as_ref();

+ 2 - 2
test/entt/meta/meta_func.cpp

@@ -332,7 +332,7 @@ TEST_F(MetaFunc, ArgsByRef) {
     entt::meta_any any{3};
     int value = 4;
 
-    ASSERT_EQ(func.invoke({}, entt::make_meta<int &>(value)).cast<int>(), 8);
+    ASSERT_EQ(func.invoke({}, entt::forward_as_meta(value)).cast<int>(), 8);
     ASSERT_EQ(func.invoke({}, any.as_ref()).cast<int>(), 6);
     ASSERT_EQ(any.cast<int>(), 6);
     ASSERT_EQ(value, 8);
@@ -434,7 +434,7 @@ TEST_F(MetaFunc, ExternalMemberFunction) {
 
     ASSERT_FALSE(registry.all_of<func_t>(entity));
 
-    func.invoke({}, entt::make_meta<entt::registry &>(registry), entity);
+    func.invoke({}, entt::forward_as_meta(registry), entity);
 
     ASSERT_TRUE(registry.all_of<func_t>(entity));
 }

+ 1 - 1
test/entt/meta/meta_handle.cpp

@@ -42,7 +42,7 @@ TEST_F(MetaHandle, Functionalities) {
     ASSERT_TRUE(handle->invoke("incr"_hs));
     ASSERT_EQ(instance.value, 1);
 
-    auto any = entt::make_meta<clazz_t &>(instance);
+    auto any = entt::forward_as_meta(instance);
     handle = entt::meta_handle{any};
 
     ASSERT_FALSE(std::as_const(handle)->invoke("decr"_hs));

+ 4 - 4
test/entt/meta/meta_pointer.cpp

@@ -182,7 +182,7 @@ TEST(MetaPointerLike, PointerToConstMoveOnlyType) {
 TEST(MetaPointerLike, AsRef) {
     int value = 0;
     int * ptr = &value;
-    entt::meta_any any{std::ref(ptr)};
+    entt::meta_any any{entt::forward_as_meta(ptr)};
 
     ASSERT_TRUE(any.type().is_pointer());
     ASSERT_TRUE(any.type().is_pointer_like());
@@ -203,8 +203,8 @@ TEST(MetaPointerLike, AsRef) {
 
 TEST(MetaPointerLike, AsConstRef) {
     int value = 42;
-    int * ptr = &value;
-    entt::meta_any any{std::cref(ptr)};
+    int * const ptr = &value;
+    entt::meta_any any{entt::forward_as_meta(ptr)};
 
     ASSERT_TRUE(any.type().is_pointer());
     ASSERT_TRUE(any.type().is_pointer_like());
@@ -312,7 +312,7 @@ TEST(MetaPointerLike, DereferencePointerToFunction) {
 
 TEST(MetaPointerLike, DereferenceSelfPointer) {
     self_ptr obj{42};
-    entt::meta_any any{std::ref(obj)};
+    entt::meta_any any{entt::forward_as_meta(obj)};
     entt::meta_any deref = *any;
 
     ASSERT_TRUE(deref);