Explorar o código

meta: internal range/iterator support

Michele Caini %!s(int64=5) %!d(string=hai) anos
pai
achega
b3a2f0e3a3
Modificáronse 3 ficheiros con 135 adicións e 58 borrados
  1. 92 29
      src/entt/meta/internal.hpp
  2. 37 25
      src/entt/meta/meta.hpp
  3. 6 4
      src/entt/meta/resolve.hpp

+ 92 - 29
src/entt/meta/internal.hpp

@@ -2,6 +2,7 @@
 #define ENTT_META_INTERNAL_HPP
 #define ENTT_META_INTERNAL_HPP
 
 
 
 
+#include <algorithm>
 #include <cstddef>
 #include <cstddef>
 #include <type_traits>
 #include <type_traits>
 #include "../core/attribute.h"
 #include "../core/attribute.h"
@@ -126,51 +127,113 @@ struct meta_type_node {
 };
 };
 
 
 
 
-template<typename Type, typename Op, typename Node>
-void visit(Op &op, Node *node) {
-    while(node) {
-        op(Type{node});
-        node = node->next;
+template<typename Node>
+struct meta_iterator {
+    using difference_type = std::ptrdiff_t;
+    using value_type = Node;
+    using pointer = value_type *;
+    using reference = value_type &;
+    using iterator_category = std::forward_iterator_tag;
+
+    meta_iterator() ENTT_NOEXCEPT = default;
+
+    meta_iterator(Node *head) ENTT_NOEXCEPT
+        : node{head}
+    {}
+
+    meta_iterator & operator++() ENTT_NOEXCEPT {
+        return node = node->next, *this;
     }
     }
-}
 
 
+    meta_iterator operator++(int) ENTT_NOEXCEPT {
+        meta_iterator orig = *this;
+        return operator++(), orig;
+    }
 
 
-template<auto Member, typename Type, typename Op>
-void visit(Op &op, const internal::meta_type_node *node) {
-    if(node) {
-        internal::visit<Type>(op, node->*Member);
-        auto *next = node->base;
+    [[nodiscard]] bool operator==(const meta_iterator &other) const ENTT_NOEXCEPT {
+        return other.node == node;
+    }
 
 
-        while(next) {
-            visit<Member, Type>(op, next->type());
-            next = next->next;
-        }
+    [[nodiscard]] bool operator!=(const meta_iterator &other) const ENTT_NOEXCEPT {
+        return !(*this == other);
     }
     }
-}
 
 
+    [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
+        return node;
+    }
+
+    [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
+        return *operator->();
+    }
+
+private:
+    Node *node{nullptr};
+};
+
+
+template<typename Node>
+struct meta_range {
+    using iterator = meta_iterator<Node>;
+    using const_iterator = meta_iterator<const Node>;
+
+    meta_range() ENTT_NOEXCEPT = default;
+
+    meta_range(Node *head)
+        : node{head}
+    {}
 
 
-template<typename Op, typename Node>
-auto find_if(const Op &op, Node *node) {
-    while(node && !op(node)) {
-        node = node->next;
+    iterator begin() ENTT_NOEXCEPT {
+        return iterator{node};
     }
     }
 
 
-    return node;
+    const_iterator begin() const ENTT_NOEXCEPT {
+        return const_iterator{node};
+    }
+
+    const_iterator cbegin() const ENTT_NOEXCEPT {
+        return begin();
+    }
+
+    iterator end() ENTT_NOEXCEPT {
+        return iterator{};
+    }
+
+    const_iterator end() const ENTT_NOEXCEPT {
+        return const_iterator{};
+    }
+
+    const_iterator cend() const ENTT_NOEXCEPT {
+        return end();
+    }
+
+private:
+    Node *node{nullptr};
+};
+
+
+template<auto Member, typename Type, typename Op>
+void visit(Op &op, const internal::meta_type_node *node) {
+    for(auto &&curr: meta_range{node->*Member}) {
+        op(Type{&curr});
+    }
+
+    for(auto &&base: meta_range{node->base}) {
+        visit<Member, Type>(op, base.type());
+    }
 }
 }
 
 
 
 
 template<auto Member, typename Op>
 template<auto Member, typename Op>
 auto find_if(const Op &op, const meta_type_node *node)
 auto find_if(const Op &op, const meta_type_node *node)
--> decltype(find_if(op, node->*Member)) {
-    decltype(find_if(op, node->*Member)) ret = nullptr;
+-> std::decay_t<decltype(node->*Member)> {
+    std::decay_t<decltype(node->*Member)> ret = nullptr;
+    meta_range range{node->*Member};
 
 
-    if(node) {
-        ret = find_if(op, node->*Member);
-        auto *next = node->base;
+    if(ret = std::find_if(range.begin(), range.end(), [&op](const auto &curr) { return op(&curr); }).operator->(); !ret) {
+        meta_range base{node->base};
 
 
-        while(next && !ret) {
-            ret = find_if<Member>(op, next->type());
-            next = next->next;
+        for(auto first = base.begin(), last = base.end(); first != last && !ret; ++first) {
+            ret = find_if<Member>(op, first->type());
         }
         }
     }
     }
 
 

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

@@ -2,6 +2,7 @@
 #define ENTT_META_META_HPP
 #define ENTT_META_META_HPP
 
 
 
 
+#include <algorithm>
 #include <cstddef>
 #include <cstddef>
 #include <functional>
 #include <functional>
 #include <type_traits>
 #include <type_traits>
@@ -222,10 +223,12 @@ public:
     [[nodiscard]] const Type * try_cast() const {
     [[nodiscard]] const Type * try_cast() const {
         void *ret = nullptr;
         void *ret = nullptr;
 
 
-        if(const auto type_id = internal::meta_info<Type>::resolve()->type_id; node && node->type_id == type_id) {
-            ret = instance;
-        } else if(const auto *base = internal::find_if<&internal::meta_type_node::base>([type_id](const auto *curr) { return curr->type()->type_id == type_id; }, node); base) {
-            ret = base->cast(instance);
+        if(node) {
+            if(const auto type_id = internal::meta_info<Type>::resolve()->type_id; node->type_id == type_id) {
+                ret = instance;
+            } else if(const auto *base = internal::find_if<&internal::meta_type_node::base>([type_id](const auto *curr) { return curr->type()->type_id == type_id; }, node); base) {
+                ret = base->cast(instance);
+            }
         }
         }
 
 
         return static_cast<const Type *>(ret);
         return static_cast<const Type *>(ret);
@@ -274,10 +277,12 @@ public:
     [[nodiscard]] meta_any convert() const {
     [[nodiscard]] meta_any convert() const {
         meta_any any{};
         meta_any any{};
 
 
-        if(const auto type_id = internal::meta_info<Type>::resolve()->type_id; node && node->type_id == type_id) {
-            any = *this;
-        } else if(const auto * const conv = internal::find_if<&internal::meta_type_node::conv>([type_id](const auto *curr) { return curr->type()->type_id == type_id; }, node); conv) {
-            any = conv->conv(instance);
+        if(node) {
+            if(const auto type_id = internal::meta_info<Type>::resolve()->type_id; node->type_id == type_id) {
+                any = *this;
+            } else if(const auto * const conv = internal::find_if<&internal::meta_type_node::conv>([type_id](const auto *curr) { return curr->type()->type_id == type_id; }, node); conv) {
+                any = conv->conv(instance);
+            }
         }
         }
 
 
         return any;
         return any;
@@ -603,7 +608,9 @@ struct meta_ctor {
     template<typename Op>
     template<typename Op>
     std::enable_if_t<std::is_invocable_v<Op, meta_prop>>
     std::enable_if_t<std::is_invocable_v<Op, meta_prop>>
     prop(Op op) const {
     prop(Op op) const {
-        internal::visit<meta_prop>(op, node->prop);
+        for(auto &&curr: internal::meta_range{node->prop}) {
+            op(meta_prop{&curr});
+        }
     }
     }
 
 
     /**
     /**
@@ -612,9 +619,8 @@ struct meta_ctor {
      * @return The property associated with the given key, if any.
      * @return The property associated with the given key, if any.
      */
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::find_if([key = std::move(key)](const auto *curr) {
-            return curr->key() == key;
-        }, node->prop);
+        internal::meta_range range{node->prop};
+        return std::find_if(range.cbegin(), range.cend(), [&key](const auto &curr) { return curr.key() == key; }).operator->();
     }
     }
 
 
     /**
     /**
@@ -740,7 +746,9 @@ struct meta_data {
     template<typename Op>
     template<typename Op>
     std::enable_if_t<std::is_invocable_v<Op, meta_prop>>
     std::enable_if_t<std::is_invocable_v<Op, meta_prop>>
     prop(Op op) const {
     prop(Op op) const {
-        internal::visit<meta_prop>(op, node->prop);
+        for(auto &&curr: internal::meta_range{node->prop}) {
+            op(meta_prop{&curr});
+        }
     }
     }
 
 
     /**
     /**
@@ -749,9 +757,8 @@ struct meta_data {
      * @return The property associated with the given key, if any.
      * @return The property associated with the given key, if any.
      */
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::find_if([key = std::move(key)](const auto *curr) {
-            return curr->key() == key;
-        }, node->prop);
+        internal::meta_range range{node->prop};
+        return std::find_if(range.cbegin(), range.cend(), [&key](const auto &curr) { return curr.key() == key; }).operator->();
     }
     }
 
 
     /**
     /**
@@ -851,7 +858,9 @@ struct meta_func {
     template<typename Op>
     template<typename Op>
     std::enable_if_t<std::is_invocable_v<Op, meta_prop>>
     std::enable_if_t<std::is_invocable_v<Op, meta_prop>>
     prop(Op op) const {
     prop(Op op) const {
-        internal::visit<meta_prop>(op, node->prop);
+        for(auto &&curr: internal::meta_range{node->prop}) {
+            op(meta_prop{&curr});
+        }
     }
     }
 
 
     /**
     /**
@@ -860,9 +869,8 @@ struct meta_func {
      * @return The property associated with the given key, if any.
      * @return The property associated with the given key, if any.
      */
      */
     [[nodiscard]] meta_prop prop(meta_any key) const {
     [[nodiscard]] meta_prop prop(meta_any key) const {
-        return internal::find_if([key = std::move(key)](const auto *curr) {
-            return curr->key() == key;
-        }, node->prop);
+        internal::meta_range range{node->prop};
+        return std::find_if(range.cbegin(), range.cend(), [&key](const auto &curr) { return curr.key() == key; }).operator->();
     }
     }
 
 
     /**
     /**
@@ -882,13 +890,15 @@ private:
 class meta_type {
 class meta_type {
     template<typename... Args, std::size_t... Indexes>
     template<typename... Args, std::size_t... Indexes>
     [[nodiscard]] auto ctor(std::index_sequence<Indexes...>) const {
     [[nodiscard]] auto ctor(std::index_sequence<Indexes...>) const {
-        return internal::find_if([](const auto *candidate) {
-            return candidate->size == sizeof...(Args) && ([](auto *from, auto *to) {
+        internal::meta_range range{node->ctor};
+
+        return std::find_if(range.cbegin(), range.cend(), [](const auto &candidate) {
+            return candidate.size == sizeof...(Args) && ([](auto *from, auto *to) {
                 return (from->type_id == to->type_id)
                 return (from->type_id == to->type_id)
                         || internal::find_if<&internal::meta_type_node::base>([to](const auto *curr) { return curr->type()->type_id == to->type_id; }, from)
                         || internal::find_if<&internal::meta_type_node::base>([to](const auto *curr) { return curr->type()->type_id == to->type_id; }, from)
                         || internal::find_if<&internal::meta_type_node::conv>([to](const auto *curr) { return curr->type()->type_id == to->type_id; }, from);
                         || internal::find_if<&internal::meta_type_node::conv>([to](const auto *curr) { return curr->type()->type_id == to->type_id; }, from);
-            }(internal::meta_info<Args>::resolve(), candidate->arg(Indexes)) && ...);
-        }, node->ctor);
+            }(internal::meta_info<Args>::resolve(), candidate.arg(Indexes)) && ...);
+        }).operator->();
     }
     }
 
 
 public:
 public:
@@ -1091,7 +1101,9 @@ public:
      */
      */
     template<typename Op>
     template<typename Op>
     void ctor(Op op) const {
     void ctor(Op op) const {
-        internal::visit<meta_ctor>(op, node->ctor);
+        for(auto &&curr: internal::meta_range{node->ctor}) {
+            op(meta_ctor{&curr});
+        }
     }
     }
 
 
     /**
     /**

+ 6 - 4
src/entt/meta/resolve.hpp

@@ -27,7 +27,9 @@ template<typename Type>
  */
  */
 template<typename Op>
 template<typename Op>
 void resolve(Op op) {
 void resolve(Op op) {
-    internal::visit<meta_type>(op, *internal::meta_context::global());
+    for(auto &&curr: internal::meta_range{*internal::meta_context::global()}) {
+        op(meta_type{&curr});
+    }
 }
 }
 
 
 
 
@@ -39,9 +41,9 @@ void resolve(Op op) {
  */
  */
 template<typename Func>
 template<typename Func>
 [[nodiscard]] meta_type resolve_if(Func func) ENTT_NOEXCEPT {
 [[nodiscard]] meta_type resolve_if(Func func) ENTT_NOEXCEPT {
-    return internal::find_if([&func](const auto *curr) {
-        return func(meta_type{curr});
-    }, *internal::meta_context::global());
+    internal::meta_range range{*internal::meta_context::global()};
+    const auto it = std::find_if(range.cbegin(), range.cend(), [&func](const auto &curr) { return func(meta_type{&curr}); });
+    return it == range.cend() ? nullptr : it.operator->();
 }
 }