meta_any: make ref to pointer-like types work in all cases

This commit is contained in:
Michele Caini
2020-12-21 08:47:18 +01:00
parent bedea4b11a
commit fa4c6bccbc
3 changed files with 56 additions and 3 deletions

View File

@@ -215,7 +215,7 @@ public:
template<typename Type>
meta_any(std::reference_wrapper<Type> value)
: storage{value},
vtable{&basic_vtable<std::remove_const_t<Type>>},
vtable{&basic_vtable<Type>},
node{internal::meta_info<Type>::resolve()}
{}

View File

@@ -105,6 +105,15 @@ template<typename>
struct is_meta_pointer_like: std::false_type {};
/**
* @brief Partial specialization to ensure that const pointer-like types are
* also accepted.
* @tparam Type Potentially pointer-like type.
*/
template<typename Type>
struct is_meta_pointer_like<const Type>: is_meta_pointer_like<Type> {};
/**
* @brief Helper variable template.
* @tparam Type Potentially pointer-like type.

View File

@@ -42,7 +42,7 @@ TEST(MetaPointerLike, DereferenceOperatorConstType) {
ASSERT_EQ(deref.try_cast<int>(), nullptr);
ASSERT_EQ(deref.try_cast<const int>(), &value);
ASSERT_DEATH(deref.cast<int &>(), ".*");
ASSERT_DEATH(deref.cast<int &>() = 0, ".*");
ASSERT_EQ(deref.cast<const int &>(), 42);
}
@@ -96,7 +96,51 @@ TEST(MetaPointerLike, PointerToConstMoveOnlyType) {
ASSERT_TRUE(any);
ASSERT_TRUE(deref);
ASSERT_DEATH(deref.cast<not_copyable_t &>(), ".*");
ASSERT_DEATH(deref.cast<not_copyable_t &>() = {}, ".*");
ASSERT_EQ(deref.try_cast<not_copyable_t>(), nullptr);
ASSERT_NE(deref.try_cast<const not_copyable_t>(), nullptr);
}
TEST(MetaPointerLike, AsRef) {
int value = 0;
int * ptr = &value;
entt::meta_any any{std::ref(ptr)};
ASSERT_TRUE(any.type().is_pointer());
ASSERT_TRUE(any.type().is_pointer_like());
ASSERT_EQ(any.type(), entt::resolve<int *>());
auto deref = *any;
ASSERT_TRUE(deref);
ASSERT_FALSE(deref.type().is_pointer());
ASSERT_FALSE(deref.type().is_pointer_like());
ASSERT_EQ(deref.type(), entt::resolve<int>());
deref.cast<int &>() = 42;
ASSERT_EQ(*any.cast<int *>(), 42);
ASSERT_EQ(value, 42);
}
TEST(MetaPointerLike, AsConstRef) {
int value = 42;
int * ptr = &value;
entt::meta_any any{std::cref(ptr)};
ASSERT_TRUE(any.type().is_pointer());
ASSERT_TRUE(any.type().is_pointer_like());
ASSERT_EQ(any.type(), entt::resolve<int *>());
auto deref = *any;
ASSERT_TRUE(deref);
ASSERT_FALSE(deref.type().is_pointer());
ASSERT_FALSE(deref.type().is_pointer_like());
ASSERT_EQ(deref.type(), entt::resolve<int>());
deref.cast<int &>() = 42;
ASSERT_EQ(*any.cast<int *>(), 42);
ASSERT_EQ(value, 42);
}