Browse Source

meta: meta_type rank/extent

Michele Caini 5 years ago
parent
commit
fac4132cb1
3 changed files with 39 additions and 9 deletions
  1. 17 4
      src/entt/meta/internal.hpp
  2. 16 5
      src/entt/meta/meta.hpp
  3. 6 0
      test/entt/meta/meta_type.cpp

+ 17 - 4
src/entt/meta/internal.hpp

@@ -5,6 +5,7 @@
 #include <algorithm>
 #include <algorithm>
 #include <cstddef>
 #include <cstddef>
 #include <type_traits>
 #include <type_traits>
+#include <utility>
 #include "../core/attribute.h"
 #include "../core/attribute.h"
 #include "../config/config.h"
 #include "../config/config.h"
 #include "../core/fwd.hpp"
 #include "../core/fwd.hpp"
@@ -114,7 +115,8 @@ struct meta_type_node {
     const bool is_function_pointer;
     const bool is_function_pointer;
     const bool is_member_object_pointer;
     const bool is_member_object_pointer;
     const bool is_member_function_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 *);
     bool(* const compare)(const void *, const void *);
     meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
     meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
     meta_type_node *(* const remove_extent)() 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>
 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");
     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>) {
         if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
             return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
             return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
         } else {
         } 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 {
     [[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
         static meta_type_node node{
         static meta_type_node node{
             type_info<Type>::id(),
             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_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
             std::is_member_object_pointer_v<Type>,
             std::is_member_object_pointer_v<Type>,
             std::is_member_function_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
             &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_pointer_t<Type>>>::resolve,
             &meta_node<std::remove_const_t<std::remove_extent_t<Type>>>::resolve
             &meta_node<std::remove_const_t<std::remove_extent_t<Type>>>::resolve

+ 16 - 5
src/entt/meta/meta.hpp

@@ -1028,12 +1028,23 @@ public:
 
 
     /**
     /**
      * @brief If a meta type refers to an array type, provides the number of
      * @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);
     }
     }
 
 
     /**
     /**

+ 6 - 0
test/entt/meta/meta_type.cpp

@@ -129,6 +129,7 @@ TEST_F(MetaType, Traits) {
     ASSERT_TRUE(entt::resolve<void>().is_void());
     ASSERT_TRUE(entt::resolve<void>().is_void());
     ASSERT_TRUE(entt::resolve<bool>().is_integral());
     ASSERT_TRUE(entt::resolve<bool>().is_integral());
     ASSERT_TRUE(entt::resolve<double>().is_floating_point());
     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<property_t>().is_enum());
     ASSERT_TRUE(entt::resolve<union_t>().is_union());
     ASSERT_TRUE(entt::resolve<union_t>().is_union());
     ASSERT_TRUE(entt::resolve<derived_t>().is_class());
     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::func)>().is_function_pointer());
     ASSERT_TRUE(entt::resolve<decltype(&clazz_t::value)>().is_member_object_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_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) {
 TEST_F(MetaType, RemovePointer) {