meta: support for pointer-like types
This commit is contained in:
1
TODO
1
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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
|
||||
std::is_member_object_pointer_v<Type>,
|
||||
std::is_member_function_pointer_v<Type>,
|
||||
is_dereferenceable_v<Type>,
|
||||
is_meta_pointer_like_v<Type>,
|
||||
has_meta_sequence_container_traits_v<Type>,
|
||||
has_meta_associative_container_traits_v<Type>,
|
||||
std::rank_v<Type>,
|
||||
|
||||
@@ -134,7 +134,7 @@ class meta_any {
|
||||
[[nodiscard]] static meta_any dereference_operator(meta_any &any) {
|
||||
meta_any other{};
|
||||
|
||||
if constexpr(is_dereferenceable_v<Type>) {
|
||||
if constexpr(is_meta_pointer_like_v<Type>) {
|
||||
if constexpr(std::is_const_v<std::remove_reference_t<decltype(*std::declval<Type>())>>) {
|
||||
other = *any.cast<Type>();
|
||||
} 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
48
src/entt/meta/pointer.hpp
Normal file
48
src/entt/meta/pointer.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef ENTT_META_POINTER_HPP
|
||||
#define ENTT_META_POINTER_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include "type_traits.hpp"
|
||||
|
||||
|
||||
namespace entt {
|
||||
|
||||
|
||||
/**
|
||||
* @brief Makes plain pointers pointer-like types for the meta system.
|
||||
* @tparam Type Element type.
|
||||
*/
|
||||
template<typename Type>
|
||||
struct is_meta_pointer_like<Type *>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta
|
||||
* system.
|
||||
* @tparam Type Element type.
|
||||
*/
|
||||
template<typename Type>
|
||||
struct is_meta_pointer_like<std::shared_ptr<Type>>
|
||||
: 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<typename Type, typename... Args>
|
||||
struct is_meta_pointer_like<std::unique_ptr<Type, Args...>>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -72,6 +72,23 @@ template<typename Type>
|
||||
inline constexpr auto has_meta_associative_container_traits_v = has_meta_associative_container_traits<Type>::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<typename>
|
||||
struct is_meta_pointer_like: std::false_type {};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Helper variable template.
|
||||
* @tparam Type Potentially pointer-like type.
|
||||
*/
|
||||
template<typename Type>
|
||||
inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like<Type>::value;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -622,79 +622,3 @@ TEST_F(MetaAny, UnmanageableType) {
|
||||
ASSERT_TRUE(std::as_const(any).convert<unmanageable_t>());
|
||||
ASSERT_FALSE(std::as_const(any).convert<int>());
|
||||
}
|
||||
|
||||
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<int>());
|
||||
|
||||
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<const int *>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_dereferenceable());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<const int *>(), 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<int *>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_dereferenceable());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<int *>(), 42);
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaAny, DereferenceOperatorSmartPointer) {
|
||||
auto value = std::make_shared<int>(0);
|
||||
entt::meta_any any{value};
|
||||
|
||||
ASSERT_FALSE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_dereferenceable());
|
||||
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_dereferenceable());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<std::shared_ptr<int>>(), 42);
|
||||
ASSERT_EQ(*value, 42);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/type_traits.hpp>
|
||||
|
||||
TEST(MetaSequenceContainer, Empty) {
|
||||
entt::meta_sequence_container container{};
|
||||
|
||||
81
test/entt/meta/meta_pointer.cpp
Normal file
81
test/entt/meta/meta_pointer.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#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>
|
||||
|
||||
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 = 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<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>());
|
||||
|
||||
deref.cast<int>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<const int *>(), 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<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);
|
||||
}
|
||||
@@ -3,10 +3,11 @@
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/pointer.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
|
||||
template<typename Type>
|
||||
void set(Type &prop, Type value) {
|
||||
@@ -164,9 +165,9 @@ TEST_F(MetaType, Traits) {
|
||||
ASSERT_TRUE(entt::resolve<decltype(&clazz_t::member)>().is_member_function_pointer());
|
||||
ASSERT_FALSE(entt::resolve<decltype(&clazz_t::value)>().is_member_function_pointer());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<int *>().is_dereferenceable());
|
||||
ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_dereferenceable());
|
||||
ASSERT_FALSE(entt::resolve<int>().is_dereferenceable());
|
||||
ASSERT_TRUE(entt::resolve<int *>().is_pointer_like());
|
||||
ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_pointer_like());
|
||||
ASSERT_FALSE(entt::resolve<int>().is_pointer_like());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<std::vector<int>>().is_sequence_container());
|
||||
ASSERT_FALSE((entt::resolve<std::map<int, char>>().is_sequence_container()));
|
||||
|
||||
Reference in New Issue
Block a user