Browse Source

meta: user defined traits for meta objects

skypjack 1 year ago
parent
commit
56ef214bf3
4 changed files with 71 additions and 17 deletions
  1. 2 3
      TODO
  2. 30 1
      src/entt/meta/factory.hpp
  3. 37 12
      src/entt/meta/meta.hpp
  4. 2 1
      src/entt/meta/node.hpp

+ 2 - 3
TODO

@@ -32,15 +32,14 @@ TODO:
 * table: pop back to support swap and pop, single column access, empty type optimization
 * checkout tools workflow
 * review constrained noexcept-ness (ie sigh)
-* offer 16b from meta_traits to users or change type
 * registry::view const invokes refresh multiple times implicitly
 * improve front (no multiple checks) and back (ie no contains) for multi-type view
 * cleanup common view from tricks to handle single swap-only and in-place, if constexpr branches
-* consider returning subrange for swap-only sparse sets or consider using filtered each for in-place storage (smilar to storage entity), cleanup views
 * exploit ref/cref in any to avoid invoking the vtable if possible
 * review meta properties and details, maybe a dense map is too much
 * self assignment support for any and meta_any
 * meta support for use defined traits (room for them on meta traits)
 * entity based component_traits
-* seek functions for meta factory (data/func/whatever)
 * investigate using any rather than shared<void> for meta properties
+* refine user defined meta traits implementation
+

+ 30 - 1
src/entt/meta/factory.hpp

@@ -9,6 +9,7 @@
 #include <type_traits>
 #include <utility>
 #include "../config/config.h"
+#include "../core/bit.hpp"
 #include "../core/fwd.hpp"
 #include "../core/type_info.hpp"
 #include "../core/type_traits.hpp"
@@ -103,6 +104,18 @@ protected:
         }
     }
 
+    void traits(const std::underlying_type_t<internal::meta_traits> value) {
+        constexpr auto shift = popcount(static_cast<std::underlying_type_t<internal::meta_traits>>(internal::meta_traits::_user_defined_traits));
+
+        if(const internal::meta_traits data{value << shift}; bucket == parent) {
+            internal::meta_context::from(*ctx).value[parent].traits |= data;
+        } else if(is_data) {
+            details->data[bucket].traits |= data;
+        } else {
+            details->func[bucket].traits |= data;
+        }
+    }
+
 public:
     basic_meta_factory(const type_info &info, meta_ctx &area)
         : ctx{&area},
@@ -480,7 +493,7 @@ public:
     }
 
     /**
-     * @brief Assigns a property to the last meta object created.
+     * @brief Assigns a property to the last created meta object.
      *
      * Both the key and the value (if any) must be at least copy constructible.
      *
@@ -499,6 +512,22 @@ public:
 
         return *this;
     }
+
+    /**
+     * @brief Sets traits on the last created meta object.
+     *
+     * The assigned value must be an enum and intended as a bitmask.
+     *
+     * @tparam Value Type of the traits value.
+     * @param value Traits value.
+     * @return A meta factory for the parent type.
+     */
+    template<typename Value>
+    meta_factory traits(const Value value) {
+        static_assert(std::is_enum_v<Value>, "Invalid enum type");
+        base_type::traits(static_cast<std::underlying_type_t<internal::meta_traits>>(static_cast<std::underlying_type_t<Value>>(value)));
+        return *this;
+    }
 };
 
 /**

+ 37 - 12
src/entt/meta/meta.hpp

@@ -9,6 +9,7 @@
 #include <utility>
 #include "../config/config.h"
 #include "../core/any.hpp"
+#include "../core/bit.hpp"
 #include "../core/fwd.hpp"
 #include "../core/iterator.hpp"
 #include "../core/type_info.hpp"
@@ -912,6 +913,18 @@ struct meta_data {
         return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
     }
 
+    /**
+     * @brief Returns all meta traits for a given meta object.
+     * @tparam Type The type to convert the meta traits to.
+     * @return The registered meta traits, if any.
+     */
+    template<typename Type>
+    [[nodiscard]] Type traits() const noexcept {
+        static_assert(std::is_enum_v<Type>, "Invalid enum type");
+        constexpr auto shift = popcount(static_cast<std::underlying_type_t<internal::meta_traits>>(internal::meta_traits::_user_defined_traits));
+        return Type{static_cast<std::underlying_type_t<Type>>(static_cast<std::underlying_type_t<internal::meta_traits>>(node->traits) >> shift)};
+    }
+
     /**
      * @brief Returns true if an object is valid, false otherwise.
      * @return True if the object is valid, false otherwise.
@@ -996,10 +1009,6 @@ struct meta_func {
 
     /**
      * @brief Invokes the underlying function, if possible.
-     *
-     * @warning
-     * The context of the arguments is **never** changed.
-     *
      * @param instance An opaque instance of the underlying type.
      * @param args Parameters to use to invoke the function.
      * @param sz Number of parameters to use to invoke the function.
@@ -1038,6 +1047,18 @@ struct meta_func {
         return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
     }
 
+    /**
+     * @brief Returns all meta traits for a given meta object.
+     * @tparam Type The type to convert the meta traits to.
+     * @return The registered meta traits, if any.
+     */
+    template<typename Type>
+    [[nodiscard]] Type traits() const noexcept {
+        static_assert(std::is_enum_v<Type>, "Invalid enum type");
+        constexpr auto shift = popcount(static_cast<std::underlying_type_t<internal::meta_traits>>(internal::meta_traits::_user_defined_traits));
+        return Type{static_cast<std::underlying_type_t<Type>>(static_cast<std::underlying_type_t<internal::meta_traits>>(node->traits) >> shift)};
+    }
+
     /**
      * @brief Returns the next overload of a given function, if any.
      * @return The next overload of the given function, if any.
@@ -1373,10 +1394,6 @@ public:
 
     /**
      * @brief Creates an instance of the underlying type, if possible.
-     *
-     * @warning
-     * The context of the arguments is **never** changed.
-     *
      * @param args Parameters to use to construct the instance.
      * @param sz Number of parameters to use to construct the instance.
      * @return A wrapper containing the new instance, if any.
@@ -1423,10 +1440,6 @@ public:
 
     /**
      * @brief Invokes a function given an identifier, if possible.
-     *
-     * @warning
-     * The context of the arguments is **never** changed.
-     *
      * @param id Unique identifier.
      * @param instance An opaque instance of the underlying type.
      * @param args Parameters to use to invoke the function.
@@ -1510,6 +1523,18 @@ public:
         return elem ? meta_prop{*ctx, *elem} : meta_prop{};
     }
 
+    /**
+     * @brief Returns all meta traits for a given meta object.
+     * @tparam Type The type to convert the meta traits to.
+     * @return The registered meta traits, if any.
+     */
+    template<typename Type>
+    [[nodiscard]] Type traits() const noexcept {
+        static_assert(std::is_enum_v<Type>, "Invalid enum type");
+        constexpr auto shift = popcount(static_cast<std::underlying_type_t<internal::meta_traits>>(internal::meta_traits::_user_defined_traits));
+        return Type{static_cast<std::underlying_type_t<Type>>(static_cast<std::underlying_type_t<internal::meta_traits>>(node.traits) >> shift)};
+    }
+
     /**
      * @brief Returns true if an object is valid, false otherwise.
      * @return True if the object is valid, false otherwise.

+ 2 - 1
src/entt/meta/node.hpp

@@ -39,7 +39,8 @@ enum class meta_traits : std::uint32_t {
     is_meta_pointer_like = 0x0200,
     is_meta_sequence_container = 0x0400,
     is_meta_associative_container = 0x0800,
-    _entt_enum_as_bitmask
+    _user_defined_traits = 0xFFFF,
+    _entt_enum_as_bitmask = 0xFFFF
 };
 
 struct meta_type_node;