diff --git a/TODO b/TODO index 0e5d46d49..41d1d8b3e 100644 --- a/TODO +++ b/TODO @@ -32,3 +32,4 @@ Next: - meta_any deref fails if operator* returns a temporary - remove dereferenceable detector from type traits (is broken) - update meta.md + - review _t diff --git a/src/entt/entt.hpp b/src/entt/entt.hpp index 9b8039899..7e35e0ab8 100644 --- a/src/entt/entt.hpp +++ b/src/entt/entt.hpp @@ -25,6 +25,7 @@ #include "meta/factory.hpp" #include "meta/internal.hpp" #include "meta/meta.hpp" +#include "meta/pointer.hpp" #include "meta/policy.hpp" #include "meta/range.hpp" #include "meta/resolve.hpp" diff --git a/src/entt/meta/internal.hpp b/src/entt/meta/internal.hpp index e5b539e4d..31bdc76bc 100644 --- a/src/entt/meta/internal.hpp +++ b/src/entt/meta/internal.hpp @@ -275,7 +275,7 @@ struct meta_type_node { const bool is_function_pointer; const bool is_member_object_pointer; const bool is_member_function_pointer; - const bool is_dereferenceable; + const bool is_pointer_like; const bool is_sequence_container; const bool is_associative_container; const size_type rank; @@ -419,7 +419,7 @@ public: std::is_pointer_v && std::is_function_v>, std::is_member_object_pointer_v, std::is_member_function_pointer_v, - is_dereferenceable_v, + is_meta_pointer_like_v, has_meta_sequence_container_traits_v, has_meta_associative_container_traits_v, std::rank_v, diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 518fad50f..02a3bc2a3 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -134,7 +134,7 @@ class meta_any { [[nodiscard]] static meta_any dereference_operator(meta_any &any) { meta_any other{}; - if constexpr(is_dereferenceable_v) { + if constexpr(is_meta_pointer_like_v) { if constexpr(std::is_const_v())>>) { other = *any.cast(); } else { @@ -1095,11 +1095,12 @@ public: } /** - * @brief Checks whether a type is dereferenceable or not. - * @return True if the underlying type is dereferenceable, false otherwise. + * @brief Checks whether a type is a pointer-like type or not. + * @return True if the underlying type is a pointer-like one, false + * otherwise. */ - [[nodiscard]] bool is_dereferenceable() const ENTT_NOEXCEPT { - return node->is_dereferenceable; + [[nodiscard]] bool is_pointer_like() const ENTT_NOEXCEPT { + return node->is_pointer_like; } /** diff --git a/src/entt/meta/pointer.hpp b/src/entt/meta/pointer.hpp new file mode 100644 index 000000000..b385af967 --- /dev/null +++ b/src/entt/meta/pointer.hpp @@ -0,0 +1,48 @@ +#ifndef ENTT_META_POINTER_HPP +#define ENTT_META_POINTER_HPP + +#include +#include +#include "type_traits.hpp" + + +namespace entt { + + +/** + * @brief Makes plain pointers pointer-like types for the meta system. + * @tparam Type Element type. + */ +template +struct is_meta_pointer_like + : std::true_type +{}; + + +/** + * @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta + * system. + * @tparam Type Element type. + */ +template +struct is_meta_pointer_like> + : std::true_type +{}; + + +/** + * @brief Makes `std::unique_ptr`s of any type pointer-like types for the meta + * system. + * @tparam Type Element type. + * @tparam Args Other arguments. + */ +template +struct is_meta_pointer_like> + : std::true_type +{}; + + +} + + +#endif diff --git a/src/entt/meta/type_traits.hpp b/src/entt/meta/type_traits.hpp index 52a0c0630..9a6ddd601 100644 --- a/src/entt/meta/type_traits.hpp +++ b/src/entt/meta/type_traits.hpp @@ -72,6 +72,23 @@ template inline constexpr auto has_meta_associative_container_traits_v = has_meta_associative_container_traits::value; +/** + * @brief Provides the member constant `value` to true if a given type is a + * pointer-like type from the point of view of the meta system, false otherwise. + * @tparam Type Potentially pointer-like type. + */ +template +struct is_meta_pointer_like: std::false_type {}; + + +/** + * @brief Helper variable template. + * @tparam Type Potentially pointer-like type. + */ +template +inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like::value; + + } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8c6233766..cfc6e24e7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -184,6 +184,7 @@ SETUP_BASIC_TEST(meta_conv entt/meta/meta_conv.cpp) SETUP_BASIC_TEST(meta_ctor entt/meta/meta_ctor.cpp) SETUP_BASIC_TEST(meta_data entt/meta/meta_data.cpp) SETUP_BASIC_TEST(meta_func entt/meta/meta_func.cpp) +SETUP_BASIC_TEST(meta_pointer entt/meta/meta_pointer.cpp) SETUP_BASIC_TEST(meta_prop entt/meta/meta_prop.cpp) SETUP_BASIC_TEST(meta_range entt/meta/meta_range.cpp) SETUP_BASIC_TEST(meta_type entt/meta/meta_type.cpp) diff --git a/test/entt/meta/meta_any.cpp b/test/entt/meta/meta_any.cpp index 0bd5358d5..a08c0470b 100644 --- a/test/entt/meta/meta_any.cpp +++ b/test/entt/meta/meta_any.cpp @@ -622,79 +622,3 @@ TEST_F(MetaAny, UnmanageableType) { ASSERT_TRUE(std::as_const(any).convert()); ASSERT_FALSE(std::as_const(any).convert()); } - -TEST_F(MetaAny, DereferenceOperatorInvalidType) { - int value = 0; - entt::meta_any any{value}; - - ASSERT_FALSE(any.type().is_pointer()); - ASSERT_FALSE(any.type().is_dereferenceable()); - ASSERT_EQ(any.type(), entt::resolve()); - - auto deref = *any; - - ASSERT_FALSE(deref); -} - -TEST_F(MetaAny, DereferenceOperatorConstType) { - const int value = 0; - entt::meta_any any{&value}; - - ASSERT_TRUE(any.type().is_pointer()); - ASSERT_TRUE(any.type().is_dereferenceable()); - ASSERT_EQ(any.type(), entt::resolve()); - - auto deref = *any; - - ASSERT_TRUE(deref); - ASSERT_FALSE(deref.type().is_pointer()); - ASSERT_FALSE(deref.type().is_dereferenceable()); - ASSERT_EQ(deref.type(), entt::resolve()); - - deref.cast() = 42; - - ASSERT_EQ(*any.cast(), 0); - ASSERT_EQ(value, 0); -} - -TEST_F(MetaAny, DereferenceOperatorRawPointer) { - int value = 0; - entt::meta_any any{&value}; - - ASSERT_TRUE(any.type().is_pointer()); - ASSERT_TRUE(any.type().is_dereferenceable()); - ASSERT_EQ(any.type(), entt::resolve()); - - auto deref = *any; - - ASSERT_TRUE(deref); - ASSERT_FALSE(deref.type().is_pointer()); - ASSERT_FALSE(deref.type().is_dereferenceable()); - ASSERT_EQ(deref.type(), entt::resolve()); - - deref.cast() = 42; - - ASSERT_EQ(*any.cast(), 42); - ASSERT_EQ(value, 42); -} - -TEST_F(MetaAny, DereferenceOperatorSmartPointer) { - auto value = std::make_shared(0); - entt::meta_any any{value}; - - ASSERT_FALSE(any.type().is_pointer()); - ASSERT_TRUE(any.type().is_dereferenceable()); - ASSERT_EQ(any.type(), entt::resolve>()); - - auto deref = *any; - - ASSERT_TRUE(deref); - ASSERT_FALSE(deref.type().is_pointer()); - ASSERT_FALSE(deref.type().is_dereferenceable()); - ASSERT_EQ(deref.type(), entt::resolve()); - - deref.cast() = 42; - - ASSERT_EQ(*any.cast>(), 42); - ASSERT_EQ(*value, 42); -} diff --git a/test/entt/meta/meta_container.cpp b/test/entt/meta/meta_container.cpp index fe684de4a..b6b01ce77 100644 --- a/test/entt/meta/meta_container.cpp +++ b/test/entt/meta/meta_container.cpp @@ -1,10 +1,8 @@ #include #include #include -#include #include #include -#include TEST(MetaSequenceContainer, Empty) { entt::meta_sequence_container container{}; diff --git a/test/entt/meta/meta_pointer.cpp b/test/entt/meta/meta_pointer.cpp new file mode 100644 index 000000000..8280a0109 --- /dev/null +++ b/test/entt/meta/meta_pointer.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include + +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()); + + auto deref = *any; + + ASSERT_FALSE(deref); +} + +TEST(MetaPointerLike, DereferenceOperatorConstType) { + const 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()); + + 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()); + + deref.cast() = 42; + + ASSERT_EQ(*any.cast(), 0); + ASSERT_EQ(value, 0); +} + +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()); + + 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()); + + deref.cast() = 42; + + ASSERT_EQ(*any.cast(), 42); + ASSERT_EQ(value, 42); +} + +TEST(MetaPointerLike, DereferenceOperatorSmartPointer) { + auto value = std::make_shared(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>()); + + 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()); + + deref.cast() = 42; + + ASSERT_EQ(*any.cast>(), 42); + ASSERT_EQ(*value, 42); +} diff --git a/test/entt/meta/meta_type.cpp b/test/entt/meta/meta_type.cpp index e62650e5d..5ba348f0f 100644 --- a/test/entt/meta/meta_type.cpp +++ b/test/entt/meta/meta_type.cpp @@ -3,10 +3,11 @@ #include #include #include +#include #include #include +#include #include -#include template void set(Type &prop, Type value) { @@ -164,9 +165,9 @@ TEST_F(MetaType, Traits) { ASSERT_TRUE(entt::resolve().is_member_function_pointer()); ASSERT_FALSE(entt::resolve().is_member_function_pointer()); - ASSERT_TRUE(entt::resolve().is_dereferenceable()); - ASSERT_TRUE(entt::resolve>().is_dereferenceable()); - ASSERT_FALSE(entt::resolve().is_dereferenceable()); + ASSERT_TRUE(entt::resolve().is_pointer_like()); + ASSERT_TRUE(entt::resolve>().is_pointer_like()); + ASSERT_FALSE(entt::resolve().is_pointer_like()); ASSERT_TRUE(entt::resolve>().is_sequence_container()); ASSERT_FALSE((entt::resolve>().is_sequence_container()));