diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index f99ddc098..51708f678 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -111,13 +111,19 @@ class basic_meta_factory { } void prop(meta_prop_node node) { + std::vector *container = nullptr; + if(bucket == parent) { - details->prop[node.id] = std::move(node); + container = &details->prop; } else if(invoke == nullptr) { - find_member(details->data)->prop[node.id] = std::move(node); + container = &find_member(details->data)->prop; } else { - find_overload()->prop[node.id] = std::move(node); + container = &find_overload()->prop; } + + std::size_t pos{}; + for(const std::size_t last = container->size(); (pos != last) && ((*container)[pos].id != node.id); ++pos) {} + (pos == container->size()) ? container->emplace_back(std::move(node)) : ((*container)[pos] = std::move(node)); } void traits(const meta_traits value) { diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 0269ab6d2..dfba05f6b 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -948,8 +948,13 @@ struct meta_data { * @return The registered meta property for the given key, if any. */ [[nodiscard]] meta_prop prop(const id_type key) const { - const auto it = node->prop.find(key); - return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; + for(auto &&elem: node->prop) { + if(elem.id == key) { + return meta_prop{*ctx, elem}; + } + } + + return meta_prop{}; } /** @@ -1088,8 +1093,13 @@ struct meta_func { * @return The registered meta property for the given key, if any. */ [[nodiscard]] meta_prop prop(const id_type key) const { - const auto it = node->prop.find(key); - return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; + for(auto &&elem: node->prop) { + if(elem.id == key) { + return meta_prop{*ctx, elem}; + } + } + + return meta_prop{}; } /*! @copydoc meta_data::traits */ @@ -1422,7 +1432,7 @@ class meta_type { * @return The registered meta data for the given identifier, if any. */ [[nodiscard]] meta_data data(const id_type id) const { - const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id); + const auto *elem = internal::deprecated_look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id); return elem ? meta_data{*ctx, *elem} : meta_data{}; } @@ -1444,7 +1454,7 @@ class meta_type { * @return The registered meta function for the given identifier, if any. */ [[nodiscard]] meta_func func(const id_type id) const { - const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id); + const auto *elem = internal::deprecated_look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id); return elem ? meta_func{*ctx, *elem} : meta_func{}; } diff --git a/src/entt/meta/node.hpp b/src/entt/meta/node.hpp index 5f1eb0e4a..b16ad6d63 100644 --- a/src/entt/meta/node.hpp +++ b/src/entt/meta/node.hpp @@ -109,7 +109,7 @@ struct meta_data_node { bool (*set)(meta_handle, meta_any){}; meta_any (*get)(const meta_ctx &, meta_handle){}; meta_custom_node custom{}; - dense_map prop{}; + std::vector prop{}; }; struct meta_func_node { @@ -123,7 +123,7 @@ struct meta_func_node { meta_any (*invoke)(const meta_ctx &, meta_handle, meta_any *const){}; std::shared_ptr next{}; meta_custom_node custom{}; - dense_map prop{}; + std::vector prop{}; }; struct meta_template_node { @@ -140,7 +140,7 @@ struct meta_type_descriptor { std::vector conv{}; dense_map data{}; dense_map func{}; - dense_map prop{}; + std::vector prop{}; }; struct meta_type_node { @@ -162,14 +162,14 @@ struct meta_type_node { }; template -auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) { +auto *deprecated_look_for(const meta_context &context, const meta_type_node &node, const id_type id) { if(node.details) { if(const auto it = (node.details.get()->*Member).find(id); it != (node.details.get()->*Member).cend()) { return &it->second; } for(auto &&curr: node.details->base) { - if(auto *elem = look_for(context, curr.second.type(context), id); elem) { + if(auto *elem = deprecated_look_for(context, curr.second.type(context), id); elem) { return elem; } } @@ -178,6 +178,25 @@ auto *look_for(const meta_context &context, const meta_type_node &node, const id return static_cast*Member)>::mapped_type *>(nullptr); } +template +auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) { + if(node.details) { + for(auto &&elem: (node.details.get()->*Member)) { + if(elem.id == id) { + return &elem; + } + } + + for(auto &&curr: node.details->base) { + if(auto *elem = look_for(context, curr.second.type(context), id); elem) { + return elem; + } + } + } + + return static_cast*Member)>::value_type *>(nullptr); +} + template meta_type_node resolve(const meta_context &) noexcept; diff --git a/src/entt/meta/range.hpp b/src/entt/meta/range.hpp index f53b5728b..34e14ee2d 100644 --- a/src/entt/meta/range.hpp +++ b/src/entt/meta/range.hpp @@ -13,7 +13,7 @@ namespace entt { /*! @cond TURN_OFF_DOXYGEN */ namespace internal { -template +template struct meta_range_iterator final { using value_type = std::pair; using pointer = input_iterator_pointer; @@ -66,6 +66,87 @@ struct meta_range_iterator final { return (*this + -value); } + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { + return {it[value].id, Type{*ctx, it[value]}}; + } + + [[nodiscard]] constexpr pointer operator->() const noexcept { + return operator*(); + } + + [[nodiscard]] constexpr reference operator*() const noexcept { + return operator[](0); + } + + template + friend constexpr std::ptrdiff_t operator-(const meta_range_iterator &, const meta_range_iterator &) noexcept; + + template + friend constexpr bool operator==(const meta_range_iterator &, const meta_range_iterator &) noexcept; + + template + friend constexpr bool operator<(const meta_range_iterator &, const meta_range_iterator &) noexcept; + +private: + It it; + const meta_ctx *ctx; +}; + +template +struct meta_range_iterator::value_type::second_type>> final { + // deprecated work-in-progress specialization + + using value_type = std::pair; + using pointer = input_iterator_pointer; + using reference = value_type; + using difference_type = std::ptrdiff_t; + using iterator_category = std::input_iterator_tag; + using iterator_concept = std::random_access_iterator_tag; + + constexpr meta_range_iterator() noexcept + : it{}, + ctx{} {} + + constexpr meta_range_iterator(const meta_ctx &area, const It iter) noexcept + : it{iter}, + ctx{&area} {} + + constexpr meta_range_iterator &operator++() noexcept { + return ++it, *this; + } + + constexpr meta_range_iterator operator++(int) noexcept { + meta_range_iterator orig = *this; + return ++(*this), orig; + } + + constexpr meta_range_iterator &operator--() noexcept { + return --it, *this; + } + + constexpr meta_range_iterator operator--(int) noexcept { + meta_range_iterator orig = *this; + return operator--(), orig; + } + + constexpr meta_range_iterator &operator+=(const difference_type value) noexcept { + it += value; + return *this; + } + + constexpr meta_range_iterator operator+(const difference_type value) const noexcept { + meta_range_iterator copy = *this; + return (copy += value); + } + + constexpr meta_range_iterator &operator-=(const difference_type value) noexcept { + return (*this += -value); + } + + constexpr meta_range_iterator operator-(const difference_type value) const noexcept { + return (*this + -value); + } + [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { return {it[value].first, Type{*ctx, it[value].second}}; }