meta: meta_type rank/extent

This commit is contained in:
Michele Caini
2020-06-12 10:10:43 +02:00
parent bf3864b2da
commit fac4132cb1
3 changed files with 39 additions and 9 deletions

View File

@@ -5,6 +5,7 @@
#include <algorithm>
#include <cstddef>
#include <type_traits>
#include <utility>
#include "../core/attribute.h"
#include "../config/config.h"
#include "../core/fwd.hpp"
@@ -114,7 +115,8 @@ struct meta_type_node {
const bool is_function_pointer;
const bool is_member_object_pointer;
const bool is_member_function_pointer;
const size_type extent;
const size_type rank;
size_type(* const extent)(size_type);
bool(* const compare)(const void *, const void *);
meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
@@ -212,10 +214,10 @@ auto find_if(const Op &op, const meta_type_node *node)
template<typename Type>
struct ENTT_API meta_node {
class ENTT_API meta_node {
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
[[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
[[nodiscard]] static auto compare(const void *lhs, const void *rhs) {
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
} else {
@@ -223,6 +225,14 @@ struct ENTT_API meta_node {
}
}
template<std::size_t... Index>
[[nodiscard]] static auto extent(meta_type_node::size_type dim, std::index_sequence<Index...>) {
meta_type_node::size_type ext{};
((ext = (dim == Index ? std::extent_v<Type, Index> : ext)), ...);
return ext;
}
public:
[[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
static meta_type_node node{
type_info<Type>::id(),
@@ -240,7 +250,10 @@ struct ENTT_API meta_node {
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>,
std::extent_v<Type>,
std::rank_v<Type>,
[](meta_type_node::size_type dim) {
return extent(dim, std::make_index_sequence<std::rank_v<Type>>{});
},
&compare, // workaround for an issue with VS2017
&meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>::resolve,
&meta_node<std::remove_const_t<std::remove_extent_t<Type>>>::resolve

View File

@@ -1028,12 +1028,23 @@ public:
/**
* @brief If a meta type refers to an array type, provides the number of
* elements of the array.
* @return The number of elements of the array if the underlying type is an
* array type, 0 otherwise.
* dimensions of the array.
* @return The number of dimensions of the array if the underlying type is
* an array type, 0 otherwise.
*/
[[nodiscard]] size_type extent() const ENTT_NOEXCEPT {
return node->extent;
[[nodiscard]] size_type rank() const ENTT_NOEXCEPT {
return node->rank;
}
/**
* @brief If a meta type refers to an array type, provides the number of
* elements along the given dimension of the array.
* @param dim
* @return The number of elements along the given dimension of the array if
* the underlying type is an array type, 0 otherwise.
*/
[[nodiscard]] size_type extent(size_type dim = {}) const ENTT_NOEXCEPT {
return node->extent(dim);
}
/**

View File

@@ -129,6 +129,7 @@ TEST_F(MetaType, Traits) {
ASSERT_TRUE(entt::resolve<void>().is_void());
ASSERT_TRUE(entt::resolve<bool>().is_integral());
ASSERT_TRUE(entt::resolve<double>().is_floating_point());
ASSERT_TRUE(entt::resolve<int[3]>().is_array());
ASSERT_TRUE(entt::resolve<property_t>().is_enum());
ASSERT_TRUE(entt::resolve<union_t>().is_union());
ASSERT_TRUE(entt::resolve<derived_t>().is_class());
@@ -136,6 +137,11 @@ TEST_F(MetaType, Traits) {
ASSERT_TRUE(entt::resolve<decltype(&clazz_t::func)>().is_function_pointer());
ASSERT_TRUE(entt::resolve<decltype(&clazz_t::value)>().is_member_object_pointer());
ASSERT_TRUE(entt::resolve<decltype(&clazz_t::member)>().is_member_function_pointer());
ASSERT_EQ(entt::resolve<int[5][3]>().rank(), 2u);
ASSERT_EQ(entt::resolve<int[5][3]>().extent(), 5u);
ASSERT_EQ(entt::resolve<int[5][3]>().extent(1u), 3u);
ASSERT_EQ(entt::resolve<int[5][3]>().extent(2u), 0u);
}
TEST_F(MetaType, RemovePointer) {