Browse Source

meta: fake vtable for meta associative containers

skypjack 2 years ago
parent
commit
5ff2b97f67
2 changed files with 84 additions and 68 deletions
  1. 50 44
      src/entt/meta/container.hpp
  2. 34 24
      src/entt/meta/meta.hpp

+ 50 - 44
src/entt/meta/container.hpp

@@ -118,62 +118,68 @@ template<typename Type>
 struct basic_meta_associative_container_traits {
 struct basic_meta_associative_container_traits {
     static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Unexpected type");
     static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Unexpected type");
 
 
+    using operation = internal::meta_associative_container_operation;
     using size_type = typename meta_associative_container::size_type;
     using size_type = typename meta_associative_container::size_type;
     using iterator = typename meta_associative_container::iterator;
     using iterator = typename meta_associative_container::iterator;
 
 
     static constexpr auto key_only = key_only_associative_container<Type>::value;
     static constexpr auto key_only = key_only_associative_container<Type>::value;
 
 
-    [[nodiscard]] static size_type size(const void *container) noexcept {
-        return static_cast<const Type *>(container)->size();
-    }
-
-    [[nodiscard]] static bool clear(void *container) {
-        static_cast<Type *>(container)->clear();
-        return true;
-    }
-
-    [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) {
-        if constexpr(reserve_aware_container<Type>::value) {
-            static_cast<Type *>(container)->reserve(sz);
+    static size_type basic_vtable(const operation op, const meta_ctx &ctx, const void *container, meta_any *key, const void *value, iterator *it) {
+        switch(const Type *cont = static_cast<const Type *>(container); op) {
+        case operation::size:
+            return cont->size();
+        case operation::clear:
+            const_cast<Type *>(cont)->clear();
             return true;
             return true;
-        } else {
-            return false;
-        }
-    }
-
-    [[nodiscard]] static iterator iter(const meta_ctx &ctx, const void *container, const bool as_const, const bool as_end) {
-        if(as_const) {
-            const auto it = as_end ? static_cast<const Type *>(container)->end() : static_cast<const Type *>(container)->begin();
-            return iterator{ctx, std::bool_constant<key_only>{}, it};
-        } else {
-            const auto it = as_end ? static_cast<Type *>(const_cast<void *>(container))->end() : static_cast<Type *>(const_cast<void *>(container))->begin();
-            return iterator{ctx, std::bool_constant<key_only>{}, it};
-        }
-    }
-
-    [[nodiscard]] static size_type insert_or_erase(void *container, meta_any &key, meta_any &value) {
-        if(auto *const cont = static_cast<Type *>(container); key.allow_cast<const typename Type::key_type &>()) {
-            if(value) {
+        case operation::reserve:
+            if constexpr(reserve_aware_container<Type>::value) {
+                const_cast<Type *>(cont)->reserve(*static_cast<const size_type *>(value));
+                return true;
+            } else {
+                break;
+            }
+        case operation::begin:
+            *it = iterator{ctx, std::bool_constant<key_only>{}, const_cast<Type *>(cont)->begin()};
+            return true;
+        case operation::end:
+            *it = iterator{ctx, std::bool_constant<key_only>{}, const_cast<Type *>(cont)->end()};
+            return true;
+        case operation::cbegin:
+            *it = iterator{ctx, std::bool_constant<key_only>{}, cont->begin()};
+            return true;
+        case operation::cend:
+            *it = iterator{ctx, std::bool_constant<key_only>{}, cont->end()};
+            return true;
+        case operation::insert:
+            if(key->allow_cast<const typename Type::key_type &>()) {
                 if constexpr(key_only) {
                 if constexpr(key_only) {
-                    return cont->insert(key.cast<const typename Type::key_type &>()).second;
+                    return const_cast<Type *>(cont)->insert(key->cast<const typename Type::key_type &>()).second;
                 } else {
                 } else {
-                    return value.allow_cast<const typename Type::mapped_type &>() && cont->emplace(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>()).second;
+                    meta_any *val = static_cast<meta_any *>(const_cast<void *>(value));
+                    return val->allow_cast<const typename Type::mapped_type &>() && const_cast<Type *>(cont)->emplace(key->cast<const typename Type::key_type &>(), val->cast<const typename Type::mapped_type &>()).second;
                 }
                 }
-            } else {
-                return cont->erase(key.cast<const typename Type::key_type &>());
             }
             }
+            break;
+        case operation::erase:
+            if(key->allow_cast<const typename Type::key_type &>()) {
+                return const_cast<Type *>(cont)->erase(key->cast<const typename Type::key_type &>());
+            }
+            break;
+        case operation::find:
+            if(key->allow_cast<const typename Type::key_type &>()) {
+                *it = iterator{ctx, std::bool_constant<key_only>{}, const_cast<Type *>(cont)->find(key->cast<const typename Type::key_type &>())};
+                return true;
+            }
+            break;
+        case operation::cfind:
+            if(key->allow_cast<const typename Type::key_type &>()) {
+                *it = iterator{ctx, std::bool_constant<key_only>{}, cont->find(key->cast<const typename Type::key_type &>())};
+                return true;
+            }
+            break;
         }
         }
 
 
-        return 0u;
-    }
-
-    [[nodiscard]] static iterator find(const meta_ctx &ctx, const void *container, const bool as_const, meta_any &key) {
-        if(key.allow_cast<const typename Type::key_type &>()) {
-            return as_const ? iterator{ctx, std::bool_constant<key_only>{}, static_cast<const Type *>(container)->find(key.cast<const typename Type::key_type &>())}
-                            : iterator{ctx, std::bool_constant<key_only>{}, static_cast<Type *>(const_cast<void *>(container))->find(key.cast<const typename Type::key_type &>())};
-        }
-
-        return iterator{};
+        return false;
     }
     }
 };
 };
 
 

+ 34 - 24
src/entt/meta/meta.hpp

@@ -46,6 +46,20 @@ enum class meta_sequence_container_operation {
     erase
     erase
 };
 };
 
 
+enum class meta_associative_container_operation {
+    size,
+    clear,
+    reserve,
+    begin,
+    end,
+    cbegin,
+    cend,
+    insert,
+    erase,
+    find,
+    cfind
+};
+
 } // namespace internal
 } // namespace internal
 
 
 /**
 /**
@@ -106,6 +120,7 @@ private:
 /*! @brief Proxy object for associative containers. */
 /*! @brief Proxy object for associative containers. */
 class meta_associative_container {
 class meta_associative_container {
     class meta_iterator;
     class meta_iterator;
+    using operation = internal::meta_associative_container_operation;
 
 
 public:
 public:
     /*! @brief Unsigned integer type. */
     /*! @brief Unsigned integer type. */
@@ -128,20 +143,15 @@ public:
     template<typename Type>
     template<typename Type>
     void rebind(any instance) noexcept {
     void rebind(any instance) noexcept {
         ENTT_ASSERT(instance.type() == type_id<Type>(), "Unexpected type");
         ENTT_ASSERT(instance.type() == type_id<Type>(), "Unexpected type");
+        key_type_node = &internal::resolve<typename Type::key_type>;
+        value_type_node = &internal::resolve<typename Type::value_type>;
 
 
         if constexpr(!meta_associative_container_traits<Type>::key_only) {
         if constexpr(!meta_associative_container_traits<Type>::key_only) {
             mapped_type_node = &internal::resolve<typename Type::mapped_type>;
             mapped_type_node = &internal::resolve<typename Type::mapped_type>;
         }
         }
 
 
         key_only_container = meta_associative_container_traits<Type>::key_only;
         key_only_container = meta_associative_container_traits<Type>::key_only;
-        key_type_node = &internal::resolve<typename Type::key_type>;
-        value_type_node = &internal::resolve<typename Type::value_type>;
-        size_fn = &meta_associative_container_traits<Type>::size;
-        clear_fn = &meta_associative_container_traits<Type>::clear;
-        reserve_fn = &meta_associative_container_traits<Type>::reserve;
-        iter_fn = &meta_associative_container_traits<Type>::iter;
-        insert_or_erase_fn = &meta_associative_container_traits<Type>::insert_or_erase;
-        find_fn = &meta_associative_container_traits<Type>::find;
+        vtable = meta_associative_container_traits<Type>::basic_vtable;
         storage = std::move(instance);
         storage = std::move(instance);
     }
     }
 
 
@@ -166,12 +176,7 @@ private:
     internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
     internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
     internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
     internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
     internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
     internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
-    size_type (*size_fn)(const void *) noexcept {};
-    bool (*clear_fn)(void *){};
-    bool (*reserve_fn)(void *, const size_type){};
-    iterator (*iter_fn)(const meta_ctx &, const void *, const bool, const bool){};
-    size_type (*insert_or_erase_fn)(void *, meta_any &, meta_any &){};
-    iterator (*find_fn)(const meta_ctx &, const void *, const bool, meta_any &){};
+    size_type (*vtable)(const operation, const meta_ctx &, const void *, meta_any *, const void *, iterator *){};
     any storage{};
     any storage{};
 };
 };
 
 
@@ -1986,27 +1991,31 @@ inline meta_sequence_container::iterator meta_sequence_container::erase(iterator
 
 
 /*! @copydoc meta_sequence_container::size */
 /*! @copydoc meta_sequence_container::size */
 [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept {
 [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept {
-    return size_fn(storage.data());
+    return vtable(operation::size, *ctx, std::as_const(storage).data(), nullptr, nullptr, nullptr);
 }
 }
 
 
 /*! @copydoc meta_sequence_container::clear */
 /*! @copydoc meta_sequence_container::clear */
 inline bool meta_associative_container::clear() {
 inline bool meta_associative_container::clear() {
-    return (storage.policy() != any_policy::cref) && clear_fn(storage.data());
+    return (storage.policy() != any_policy::cref) && vtable(operation::clear, *ctx, storage.data(), nullptr, nullptr, nullptr);
 }
 }
 
 
 /*! @copydoc meta_sequence_container::reserve */
 /*! @copydoc meta_sequence_container::reserve */
 inline bool meta_associative_container::reserve(const size_type sz) {
 inline bool meta_associative_container::reserve(const size_type sz) {
-    return (storage.policy() != any_policy::cref) && reserve_fn(storage.data(), sz);
+    return (storage.policy() != any_policy::cref) && vtable(operation::reserve, *ctx, storage.data(), nullptr, &sz, nullptr);
 }
 }
 
 
 /*! @copydoc meta_sequence_container::begin */
 /*! @copydoc meta_sequence_container::begin */
 [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
 [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
-    return iter_fn(*ctx, std::as_const(storage).data(), (storage.policy() == any_policy::cref), false);
+    iterator it{};
+    vtable(storage.policy() == any_policy::cref ? operation::cbegin : operation::begin, *ctx, std::as_const(storage).data(), nullptr, nullptr, &it);
+    return it;
 }
 }
 
 
 /*! @copydoc meta_sequence_container::end */
 /*! @copydoc meta_sequence_container::end */
 [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
 [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
-    return iter_fn(*ctx, std::as_const(storage).data(), (storage.policy() == any_policy::cref), true);
+    iterator it{};
+    vtable(storage.policy() == any_policy::cref ? operation::cend : operation::end, *ctx, std::as_const(storage).data(), nullptr, nullptr, &it);
+    return it;
 }
 }
 
 
 /**
 /**
@@ -2015,8 +2024,7 @@ inline bool meta_associative_container::reserve(const size_type sz) {
  * @return A bool denoting whether the insertion took place.
  * @return A bool denoting whether the insertion took place.
  */
  */
 inline bool meta_associative_container::insert(meta_any key) {
 inline bool meta_associative_container::insert(meta_any key) {
-    meta_any value{*ctx, std::in_place_type<void>};
-    return (storage.policy() != any_policy::cref) && (insert_or_erase_fn(storage.data(), key, value) != 0u);
+    return ((storage.policy() != any_policy::cref) && vtable(operation::insert, *ctx, storage.data(), &key, nullptr, nullptr));
 }
 }
 
 
 /**
 /**
@@ -2026,7 +2034,7 @@ inline bool meta_associative_container::insert(meta_any key) {
  * @return A bool denoting whether the insertion took place.
  * @return A bool denoting whether the insertion took place.
  */
  */
 inline bool meta_associative_container::insert(meta_any key, meta_any value) {
 inline bool meta_associative_container::insert(meta_any key, meta_any value) {
-    return (storage.policy() != any_policy::cref) && (insert_or_erase_fn(storage.data(), key, value) != 0u);
+    return ((storage.policy() != any_policy::cref) && vtable(operation::insert, *ctx, storage.data(), &key, &value, nullptr));
 }
 }
 
 
 /**
 /**
@@ -2035,7 +2043,7 @@ inline bool meta_associative_container::insert(meta_any key, meta_any value) {
  * @return A bool denoting whether the removal took place.
  * @return A bool denoting whether the removal took place.
  */
  */
 inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) {
 inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) {
-    return insert(std::move(key), meta_any{meta_ctx_arg, *ctx});
+    return ((storage.policy() != any_policy::cref) && vtable(operation::erase, *ctx, storage.data(), &key, nullptr, nullptr));
 }
 }
 
 
 /**
 /**
@@ -2044,7 +2052,9 @@ inline meta_associative_container::size_type meta_associative_container::erase(m
  * @return An iterator to the element with the given key, if any.
  * @return An iterator to the element with the given key, if any.
  */
  */
 [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) {
 [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) {
-    return find_fn(*ctx, std::as_const(storage).data(), (storage.policy() == any_policy::cref), key);
+    iterator it{};
+    vtable(storage.policy() == any_policy::cref ? operation::cfind : operation::find, *ctx, std::as_const(storage).data(), &key, nullptr, &it);
+    return it;
 }
 }
 
 
 /**
 /**