| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- #include <memory>
- #include <type_traits>
- #include <gtest/gtest.h>
- #include <entt/core/hashed_string.hpp>
- #include <entt/meta/meta.hpp>
- #include <entt/meta/pointer.hpp>
- #include <entt/meta/resolve.hpp>
- template<typename Type>
- struct wrapped_shared_ptr {
- wrapped_shared_ptr(Type init): ptr{new Type {init}} {}
- Type & deref() const { return *ptr; }
- private:
- std::shared_ptr<Type> ptr;
- };
- struct self_ptr {
- using element_type = self_ptr;
- self_ptr(int v): value{v} {}
- const self_ptr & operator*() const { return *this; }
- int value;
- };
- struct proxy_ptr {
- using element_type = proxy_ptr;
- proxy_ptr(int &v): value{&v} {}
- proxy_ptr operator*() const { return *this; }
- int *value;
- };
- template<typename Type>
- struct adl_wrapped_shared_ptr: wrapped_shared_ptr<Type> {};
- template<typename Type>
- struct spec_wrapped_shared_ptr: wrapped_shared_ptr<Type> {};
- template<typename Type>
- struct entt::is_meta_pointer_like<adl_wrapped_shared_ptr<Type>>: std::true_type {};
- template<typename Type>
- struct entt::is_meta_pointer_like<spec_wrapped_shared_ptr<Type>>: std::true_type {};
- template<>
- struct entt::is_meta_pointer_like<self_ptr>: std::true_type {};
- template<>
- struct entt::is_meta_pointer_like<proxy_ptr>: std::true_type {};
- template<typename Type>
- struct entt::adl_meta_pointer_like<spec_wrapped_shared_ptr<Type>> {
- static decltype(auto) dereference(const spec_wrapped_shared_ptr<Type> &ptr) {
- return ptr.deref();
- }
- };
- template<typename Type>
- Type & dereference_meta_pointer_like(const adl_wrapped_shared_ptr<Type> &ptr) {
- return ptr.deref();
- }
- int test_function() { return 42; }
- struct not_copyable_t {
- not_copyable_t() = default;
- not_copyable_t(const not_copyable_t &) = delete;
- not_copyable_t(not_copyable_t &&) = default;
- not_copyable_t & operator=(const not_copyable_t &) = delete;
- not_copyable_t & operator=(not_copyable_t &&) = default;
- };
- TEST(MetaPointerLike, DereferenceOperatorInvalidType) {
- int value = 0;
- entt::meta_any any{value};
- ASSERT_FALSE(any.type().is_pointer());
- ASSERT_FALSE(any.type().is_pointer_like());
- ASSERT_EQ(any.type(), entt::resolve<int>());
- auto deref = *any;
- ASSERT_FALSE(deref);
- }
- TEST(MetaPointerLike, DereferenceOperatorConstType) {
- const int value = 42;
- entt::meta_any any{&value};
- ASSERT_TRUE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- ASSERT_EQ(any.type(), entt::resolve<const 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>());
- ASSERT_EQ(deref.try_cast<int>(), nullptr);
- ASSERT_EQ(deref.try_cast<const int>(), &value);
- ASSERT_DEATH(deref.cast<int &>() = 0, "");
- ASSERT_EQ(deref.cast<const int &>(), 42);
- }
- TEST(MetaPointerLike, DereferenceOperatorConstAny) {
- auto test = [](const entt::meta_any any) {
- 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>());
- ASSERT_EQ(deref.try_cast<int>(), nullptr);
- ASSERT_NE(deref.try_cast<const int>(), nullptr);
- ASSERT_DEATH(deref.cast<int &>() = 0, "");
- ASSERT_EQ(deref.cast<const int &>(), 42);
- };
- int value = 42;
- test(&value);
- test(&std::as_const(value));
- }
- TEST(MetaPointerLike, DereferenceOperatorRawPointer) {
- int value = 0;
- entt::meta_any any{&value};
- 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, DereferenceOperatorSmartPointer) {
- auto value = std::make_shared<int>(0);
- entt::meta_any any{value};
- ASSERT_FALSE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- ASSERT_EQ(any.type(), entt::resolve<std::shared_ptr<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<std::shared_ptr<int>>(), 42);
- ASSERT_EQ(*value, 42);
- }
- TEST(MetaPointerLike, PointerToConstMoveOnlyType) {
- const not_copyable_t instance;
- entt::meta_any any{&instance};
- auto deref = *any;
- ASSERT_TRUE(any);
- ASSERT_TRUE(deref);
- ASSERT_EQ(deref.try_cast<not_copyable_t>(), nullptr);
- ASSERT_NE(deref.try_cast<const not_copyable_t>(), nullptr);
- ASSERT_EQ(&deref.cast<const not_copyable_t &>(), &instance);
- }
- 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);
- }
- TEST(MetaPointerLike, DereferenceOverload) {
- auto test = [](entt::meta_any any) {
- ASSERT_FALSE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- 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>());
- ASSERT_EQ(deref.cast<int &>(), 42);
- ASSERT_EQ(deref.cast<const int &>(), 42);
- };
- test(adl_wrapped_shared_ptr<int>{42});
- test(spec_wrapped_shared_ptr<int>{42});
- }
- TEST(MetaPointerLike, DereferencePointerToConstOverload) {
- auto test = [](entt::meta_any any) {
- ASSERT_FALSE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- 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>());
- ASSERT_DEATH(deref.cast<int &>() = 42, "");
- ASSERT_EQ(deref.cast<const int &>(), 42);
- };
- test(adl_wrapped_shared_ptr<const int>{42});
- test(spec_wrapped_shared_ptr<const int>{42});
- }
- TEST(MetaPointerLike, DereferencePointerToVoid) {
- auto test = [](entt::meta_any any) {
- ASSERT_TRUE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- ASSERT_EQ(any.type().remove_pointer(), entt::resolve<void>());
- auto deref = *any;
- ASSERT_FALSE(deref);
- };
- test(static_cast<void *>(nullptr));
- test(static_cast<const void *>(nullptr));
- }
- TEST(MetaPointerLike, DereferenceSmartPointerToVoid) {
- auto test = [](entt::meta_any any) {
- ASSERT_TRUE(any.type().is_class());
- ASSERT_FALSE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- auto deref = *any;
- ASSERT_FALSE(deref);
- };
- test(std::shared_ptr<void>{});
- test(std::unique_ptr<void, void(*)(void *)>{nullptr, nullptr});
- }
- TEST(MetaPointerLike, DereferencePointerToFunction) {
- auto test = [](entt::meta_any any) {
- ASSERT_TRUE(any.type().is_pointer());
- ASSERT_TRUE(any.type().is_pointer_like());
- ASSERT_EQ(any.type().remove_pointer(), entt::resolve<int()>());
- ASSERT_NE(any.try_cast<int(*)()>(), nullptr);
- ASSERT_EQ(any.cast<int(*)()>()(), 42);
- };
- test(entt::meta_any{&test_function});
- test(*entt::meta_any{&test_function});
- test(**entt::meta_any{&test_function});
- }
- TEST(MetaPointerLike, DereferenceSelfPointer) {
- self_ptr obj{42};
- entt::meta_any any{std::ref(obj)};
- entt::meta_any deref = *any;
- ASSERT_TRUE(deref);
- ASSERT_TRUE(any.type().is_pointer_like());
- ASSERT_EQ(deref.cast<const self_ptr &>().value, obj.value);
- ASSERT_FALSE(deref.try_cast<self_ptr>());
- }
- TEST(MetaPointerLike, DereferenceProxyPointer) {
- int value = 3;
- proxy_ptr obj{value};
- entt::meta_any any{obj};
- entt::meta_any deref = *any;
- ASSERT_TRUE(deref);
- ASSERT_TRUE(any.type().is_pointer_like());
- ASSERT_EQ(*deref.cast<const proxy_ptr &>().value, value);
- ASSERT_TRUE(deref.try_cast<proxy_ptr>());
- *deref.cast<proxy_ptr &>().value = 42;
- ASSERT_EQ(value, 42);
- }
|