Преглед изворни кода

meta: container support review (less instantiations, faster to compile)

Michele Caini пре 4 година
родитељ
комит
6e925c7cdd
4 измењених фајлова са 162 додато и 449 уклоњено
  1. 134 268
      src/entt/meta/container.hpp
  2. 26 157
      src/entt/meta/meta.hpp
  3. 0 24
      src/entt/meta/type_traits.hpp
  4. 2 0
      test/entt/meta/meta_type.cpp

+ 134 - 268
src/entt/meta/container.hpp

@@ -5,13 +5,10 @@
 #include <array>
 #include <array>
 #include <map>
 #include <map>
 #include <set>
 #include <set>
-#include <type_traits>
 #include <unordered_map>
 #include <unordered_map>
 #include <unordered_set>
 #include <unordered_set>
-#include <utility>
 #include <vector>
 #include <vector>
-#include "../config/config.h"
-#include "../core/type_traits.hpp"
+#include "meta.hpp"
 #include "type_traits.hpp"
 #include "type_traits.hpp"
 
 
 
 
@@ -19,275 +16,183 @@ namespace entt {
 
 
 
 
 /**
 /**
- * @brief Container traits.
- * @tparam Container Type of the underlying container.
- * @tparam Trait Traits associated with the underlying container.
+ * @cond TURN_OFF_DOXYGEN
+ * Internal details not to be documented.
  */
  */
-template<typename Container, template<typename> class... Trait>
-struct meta_container_traits: public Trait<Container>... {};
 
 
 
 
-/**
- * @brief Basic STL-compatible container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct basic_container {
-    /**
-     * @brief Returns the size of the given container.
-     * @param cont The container for which to return the size.
-     * @return The size of the given container.
-     */
-    [[nodiscard]] static typename Container::size_type size(const Container &cont) ENTT_NOEXCEPT {
-        return cont.size();
-    }
+namespace internal {
+
+
+template<typename, typename = void>
+struct is_dynamic_sequence_container: std::false_type {};
+
+template<typename Type>
+struct is_dynamic_sequence_container<Type, std::void_t<decltype(&Type::clear)>>: std::true_type {};
+
 
 
-    /**
-     * @brief Returns an iterator to the first element of the given container.
-     * @param cont The container for which to return the iterator.
-     * @return An iterator to the first element of the given container.
-     */
-    [[nodiscard]] static typename Container::iterator begin(Container &cont) {
-        return cont.begin();
+template<typename, typename = void>
+struct is_key_only_meta_associative_container: std::true_type {};
+
+template<typename Type>
+struct is_key_only_meta_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {};
+
+
+template<typename Type>
+struct basic_meta_sequence_container_traits {
+    using iterator = meta_sequence_container::iterator;
+    using size_type = std::size_t;
+
+    [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
+        return any_cast<const Type &>(container).size();
     }
     }
 
 
-    /**
-     * @brief Returns an iterator to the first element of the given container.
-     * @param cont The container for which to return the iterator.
-     * @return An iterator to the first element of the given container.
-     */
-    [[nodiscard]] static typename Container::const_iterator cbegin(const Container &cont) {
-        return cont.begin();
+    [[nodiscard]] static bool resize(any &container, size_type sz) {
+        if constexpr(is_dynamic_sequence_container<Type>::value) {
+            auto * const cont = any_cast<Type>(&container);
+            return cont && (cont->resize(sz), true);
+        } else {
+            return false;
+        }
     }
     }
 
 
-    /**
-     * @brief Returns an iterator past the last element of the given container.
-     * @param cont The container for which to return the iterator.
-     * @return An iterator past the last element of the given container.
-     */
-    [[nodiscard]] static typename Container::iterator end(Container &cont) {
-        return cont.end();
+    [[nodiscard]] static bool clear(any &container) {
+        if constexpr(is_dynamic_sequence_container<Type>::value) {
+            auto * const cont = any_cast<Type>(&container);
+            return cont && (cont->clear(), true);
+        } else {
+            return false;
+        }
     }
     }
 
 
-    /**
-     * @brief Returns an iterator past the last element of the given container.
-     * @param cont The container for which to return the iterator.
-     * @return An iterator past the last element of the given container.
-     */
-    [[nodiscard]] static typename Container::const_iterator cend(const Container &cont) {
-        return cont.end();
+    [[nodiscard]] static iterator begin(any &container) {
+        if(auto * const cont = any_cast<Type>(&container); cont) {
+            return iterator{cont->begin()};
+        }
+
+        return iterator{any_cast<const Type &>(container).begin()};
     }
     }
-};
 
 
+    [[nodiscard]] static iterator end(any &container) {
+        if(auto * const cont = any_cast<Type>(&container); cont) {
+            return iterator{cont->end()};
+        }
 
 
-/**
- * @brief Basic STL-compatible associative container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct basic_associative_container {
-    /**
-     * @brief Returns an iterator to the element with key equivalent to the
-     * given one, if any.
-     * @param cont The container in which to search for the element.
-     * @param key The key of the element to search.
-     * @return An iterator to the element with the given key, if any.
-     */
-    [[nodiscard]] static typename Container::iterator find(Container &cont, const typename Container::key_type &key) {
-        return cont.find(key);
+        return iterator{any_cast<const Type &>(container).end()};
     }
     }
 
 
-    /*! @copydoc find */
-    [[nodiscard]] static typename Container::const_iterator cfind(const Container &cont, const typename Container::key_type &key) {
-        return cont.find(key);
+    [[nodiscard]] static std::pair<iterator, bool> insert(any &container, iterator it, meta_any &value) {
+        if constexpr(is_dynamic_sequence_container<Type>::value) {
+            if(auto * const cont = any_cast<Type>(&container); cont) {
+                // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
+                if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
+                    const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
+                    return { iterator{cont->insert(any_cast<const typename Type::iterator &>(it.base()), element ? *element : value.cast<typename Type::value_type>())}, true };
+                }
+            }
+        }
+
+        return {};
     }
     }
-};
 
 
+    [[nodiscard]] static std::pair<iterator, bool> erase(any &container, iterator it) {
+        if constexpr(is_dynamic_sequence_container<Type>::value) {
+            if(auto * const cont = any_cast<Type>(&container); cont) {
+                return { iterator{cont->erase(any_cast<const typename Type::iterator &>(it.base()))}, true };
+            }
+        }
 
 
-/**
- * @brief Basic STL-compatible dynamic container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct basic_dynamic_container {
-    /**
-     * @brief Clears the content of the given container.
-     * @param cont The container for which to clear the content.
-     * @return True in case of success, false otherwise.
-     */
-    [[nodiscard]] static bool clear([[maybe_unused]] Container &cont) {
-        return cont.clear(), true;
+        return {};
     }
     }
-};
 
 
+    [[nodiscard]] static meta_any get(any &container, size_type pos) {
+        if(auto * const cont = any_cast<Type>(&container); cont) {
+            return meta_any{std::in_place_type<typename Type::reference>, (*cont)[pos]};
+        }
 
 
-/**
- * @brief Basic STL-compatible dynamic associative container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct basic_dynamic_associative_container {
-    /**
-     * @brief Removes the specified element from the given container.
-     * @param cont The container from which to remove the element.
-     * @param key The element to remove.
-     * @return A bool denoting whether the removal took place.
-     */
-    [[nodiscard]] static bool erase([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
-        const auto sz = cont.size();
-        return cont.erase(key) != sz;
+        return meta_any{std::in_place_type<typename Type::const_reference>, any_cast<const Type &>(container)[pos]};
     }
     }
 };
 };
 
 
 
 
-/**
- * @brief Basic STL-compatible sequence container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct basic_sequence_container {
-    /**
-     * @brief Returns a reference to the element at the specified location of
-     * the given container (no bounds checking is performed).
-     * @param cont The container from which to get the element.
-     * @param pos The position of the element to return.
-     * @return A reference to the requested element.
-     */
-    [[nodiscard]] static typename Container::reference get(Container &cont, typename Container::size_type pos) {
-        return cont[pos];
-    }
+template<typename Type>
+struct basic_meta_associative_container_traits {
+    using iterator = meta_associative_container::iterator;
+    using size_type = std::size_t;
 
 
-    /*! @copydoc get */
-    [[nodiscard]] static typename Container::const_reference cget(const Container &cont, typename Container::size_type pos) {
-        return cont[pos];
+    [[nodiscard]] static constexpr bool key_only() ENTT_NOEXCEPT {
+        return is_key_only_meta_associative_container<Type>::value;
     }
     }
-};
 
 
-
-/**
- * @brief STL-compatible dynamic associative key-only container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct dynamic_associative_key_only_container {
-    /**
-     * @brief Inserts an element into the given container.
-     * @param cont The container in which to insert the element.
-     * @param key The element to insert.
-     * @return A bool denoting whether the insertion took place.
-     */
-    [[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key) {
-        return cont.insert(key).second;
+    [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
+        return any_cast<const Type &>(container).size();
     }
     }
-};
-
 
 
-/**
- * @brief STL-compatible dynamic key-value associative container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct dynamic_associative_key_value_container {
-    /**
-     * @brief Inserts an element (a key/value pair) into the given container.
-     * @param cont The container in which to insert the element.
-     * @param key The key of the element to insert.
-     * @param value The value of the element to insert.
-     * @return A bool denoting whether the insertion took place.
-     */
-    [[nodiscard]] static bool insert([[maybe_unused]] Container &cont, [[maybe_unused]] const typename Container::key_type &key, [[maybe_unused]] const typename Container::mapped_type &value) {
-        return cont.insert(std::make_pair(key, value)).second;
+    [[nodiscard]] static bool clear(any &container) {
+        auto * const cont = any_cast<Type>(&container);
+        return cont && (cont->clear(), true);
     }
     }
-};
 
 
+    [[nodiscard]] static iterator begin(any &container) {
+        if(auto * const cont = any_cast<Type>(&container); cont) {
+            return iterator{std::integral_constant<bool, key_only()>{}, cont->begin()};
+        }
 
 
-/**
- * @brief STL-compatible dynamic sequence container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct dynamic_sequence_container {
-    /**
-     * @brief Resizes the given container to contain the given number of
-     * elements.
-     * @param cont The container to resize.
-     * @param sz The new size of the container.
-     * @return True in case of success, false otherwise.
-     */
-    [[nodiscard]] static bool resize([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::size_type sz) {
-        return cont.resize(sz), true;
+        return iterator{std::integral_constant<bool, key_only()>{}, any_cast<const Type &>(container).begin()};
     }
     }
 
 
-    /**
-     * @brief Inserts an element at the specified location of the given
-     * container.
-     * @param cont The container into which to insert the element.
-     * @param it Iterator before which the element will be inserted.
-     * @param value Element value to insert.
-     * @return A pair consisting of an iterator to the inserted element (in case
-     * of success) and a bool denoting whether the insertion took place.
-     */
-    [[nodiscard]] static std::pair<typename Container::iterator, bool> insert([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it, [[maybe_unused]] const typename Container::value_type &value) {
-        return { cont.insert(it, value), true };
-    }
+    [[nodiscard]] static iterator end(any &container) {
+        if(auto * const cont = any_cast<Type>(&container); cont) {
+            return iterator{std::integral_constant<bool, key_only()>{}, cont->end()};
+        }
 
 
-    /**
-     * @brief Removes the element at the specified location from the given
-     * container.
-     * @param cont The container from which to remove the element.
-     * @param it Iterator to the element to remove.
-     * @return A pair consisting of an iterator following the last removed
-     * element (in case of success) and a bool denoting whether the insertion
-     * took place.
-     */
-    [[nodiscard]] static std::pair<typename Container::iterator, bool> erase([[maybe_unused]] Container &cont, [[maybe_unused]] typename Container::const_iterator it) {
-        return { cont.erase(it), true };
+        return iterator{std::integral_constant<bool, key_only()>{}, any_cast<const Type &>(container).end()};
     }
     }
-};
 
 
+    [[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) {
+        if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
+            if constexpr(is_key_only_meta_associative_container<Type>::value) {
+                return cont->insert(key.cast<const typename Type::key_type &>()).second;
+            } else {
+                return value.allow_cast<const typename Type::mapped_type &>()
+                    && cont->insert(std::make_pair(key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>())).second;
+            }
+        }
 
 
-/**
- * @brief STL-compatible fixed sequence container traits
- * @tparam Container The type of the container.
- */
-template<typename Container>
-struct fixed_sequence_container {
-    /**
-     * @brief Does nothing.
-     * @return False to indicate failure in all cases.
-     */
-    [[nodiscard]] static bool resize(const Container &, typename Container::size_type) {
         return false;
         return false;
     }
     }
 
 
-    /**
-     * @brief Does nothing.
-     * @return False to indicate failure in all cases.
-     */
-    [[nodiscard]] static bool clear(const Container &) {
+    [[nodiscard]] static bool erase(any &container, meta_any &key) {
+        if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
+            return (cont->erase(key.cast<const typename Type::key_type &>()) != cont->size());
+        }
+
         return false;
         return false;
     }
     }
 
 
-    /**
-     * @brief Does nothing.
-     * @return A pair consisting of an invalid iterator and a false value to
-     * indicate failure in all cases.
-     */
-    [[nodiscard]] static std::pair<typename Container::iterator, bool> insert(const Container &, typename Container::const_iterator, const typename Container::value_type &) {
-        return { {}, false };
-    }
+    [[nodiscard]] static iterator find(any &container, meta_any &key) {
+        if(key.allow_cast<const typename Type::key_type &>()) {
+            if(auto * const cont = any_cast<Type>(&container); cont) {
+                return iterator{std::integral_constant<bool, key_only()>{}, cont->find(key.cast<const typename Type::key_type &>())};
+            }
+
+            return iterator{std::integral_constant<bool, key_only()>{}, any_cast<const Type &>(container).find(key.cast<const typename Type::key_type &>())};
+        }
 
 
-    /**
-     * @brief Does nothing.
-     * @return A pair consisting of an invalid iterator and a false value to
-     * indicate failure in all cases.
-     */
-    [[nodiscard]] static std::pair<typename Container::iterator, bool> erase(const Container &, typename Container::const_iterator) {
-        return { {}, false };
+        return {};
     }
     }
 };
 };
 
 
 
 
+}
+
+
+/**
+ * Internal details not to be documented.
+ * @endcond
+ */
+
+
 /**
 /**
  * @brief Meta sequence container traits for `std::vector`s of any type.
  * @brief Meta sequence container traits for `std::vector`s of any type.
  * @tparam Type The type of elements.
  * @tparam Type The type of elements.
@@ -295,13 +200,7 @@ struct fixed_sequence_container {
  */
  */
 template<typename Type, typename... Args>
 template<typename Type, typename... Args>
 struct meta_sequence_container_traits<std::vector<Type, Args...>>
 struct meta_sequence_container_traits<std::vector<Type, Args...>>
-        : meta_container_traits<
-              std::vector<Type, Args...>,
-              basic_container,
-              basic_dynamic_container,
-              basic_sequence_container,
-              dynamic_sequence_container
-          >
+    : internal::basic_meta_sequence_container_traits<std::vector<Type, Args...>>
 {};
 {};
 
 
 
 
@@ -312,12 +211,7 @@ struct meta_sequence_container_traits<std::vector<Type, Args...>>
  */
  */
 template<typename Type, auto N>
 template<typename Type, auto N>
 struct meta_sequence_container_traits<std::array<Type, N>>
 struct meta_sequence_container_traits<std::array<Type, N>>
-        : meta_container_traits<
-              std::array<Type, N>,
-              basic_container,
-              basic_sequence_container,
-              fixed_sequence_container
-          >
+    : internal::basic_meta_sequence_container_traits<std::array<Type, N>>
 {};
 {};
 
 
 
 
@@ -329,14 +223,7 @@ struct meta_sequence_container_traits<std::array<Type, N>>
  */
  */
 template<typename Key, typename Value, typename... Args>
 template<typename Key, typename Value, typename... Args>
 struct meta_associative_container_traits<std::map<Key, Value, Args...>>
 struct meta_associative_container_traits<std::map<Key, Value, Args...>>
-        : meta_container_traits<
-              std::map<Key, Value, Args...>,
-              basic_container,
-              basic_associative_container,
-              basic_dynamic_container,
-              basic_dynamic_associative_container,
-              dynamic_associative_key_value_container
-          >
+    : internal::basic_meta_associative_container_traits<std::map<Key, Value, Args...>>
 {};
 {};
 
 
 
 
@@ -349,14 +236,7 @@ struct meta_associative_container_traits<std::map<Key, Value, Args...>>
  */
  */
 template<typename Key, typename Value, typename... Args>
 template<typename Key, typename Value, typename... Args>
 struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
 struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
-        : meta_container_traits<
-              std::unordered_map<Key, Value, Args...>,
-              basic_container,
-              basic_associative_container,
-              basic_dynamic_container,
-              basic_dynamic_associative_container,
-              dynamic_associative_key_value_container
-          >
+    : internal::basic_meta_associative_container_traits<std::unordered_map<Key, Value, Args...>>
 {};
 {};
 
 
 
 
@@ -367,14 +247,7 @@ struct meta_associative_container_traits<std::unordered_map<Key, Value, Args...>
  */
  */
 template<typename Key, typename... Args>
 template<typename Key, typename... Args>
 struct meta_associative_container_traits<std::set<Key, Args...>>
 struct meta_associative_container_traits<std::set<Key, Args...>>
-        : meta_container_traits<
-              std::set<Key, Args...>,
-              basic_container,
-              basic_associative_container,
-              basic_dynamic_container,
-              basic_dynamic_associative_container,
-              dynamic_associative_key_only_container
-          >
+    : internal::basic_meta_associative_container_traits<std::set<Key, Args...>>
 {};
 {};
 
 
 
 
@@ -386,14 +259,7 @@ struct meta_associative_container_traits<std::set<Key, Args...>>
  */
  */
 template<typename Key, typename... Args>
 template<typename Key, typename... Args>
 struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
 struct meta_associative_container_traits<std::unordered_set<Key, Args...>>
-        : meta_container_traits<
-              std::unordered_set<Key, Args...>,
-              basic_container,
-              basic_associative_container,
-              basic_dynamic_container,
-              basic_dynamic_associative_container,
-              dynamic_associative_key_only_container
-          >
+    : internal::basic_meta_associative_container_traits<std::unordered_set<Key, Args...>>
 {};
 {};
 
 
 
 

+ 26 - 157
src/entt/meta/meta.hpp

@@ -30,9 +30,6 @@ class meta_type;
 
 
 /*! @brief Proxy object for sequence containers. */
 /*! @brief Proxy object for sequence containers. */
 class meta_sequence_container {
 class meta_sequence_container {
-    template<typename>
-    struct meta_sequence_container_proxy;
-
     class meta_iterator;
     class meta_iterator;
 
 
 public:
 public:
@@ -52,14 +49,14 @@ public:
     template<typename Type>
     template<typename Type>
     meta_sequence_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
     meta_sequence_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
         : value_type_node{internal::meta_info<typename Type::value_type>::resolve()},
         : value_type_node{internal::meta_info<typename Type::value_type>::resolve()},
-          size_fn{&meta_sequence_container_proxy<Type>::size},
-          resize_fn{&meta_sequence_container_proxy<Type>::resize},
-          clear_fn{&meta_sequence_container_proxy<Type>::clear},
-          begin_fn{&meta_sequence_container_proxy<Type>::begin},
-          end_fn{&meta_sequence_container_proxy<Type>::end},
-          insert_fn{&meta_sequence_container_proxy<Type>::insert},
-          erase_fn{&meta_sequence_container_proxy<Type>::erase},
-          get_fn{&meta_sequence_container_proxy<Type>::get},
+          size_fn{&meta_sequence_container_traits<Type>::size},
+          resize_fn{&meta_sequence_container_traits<Type>::resize},
+          clear_fn{&meta_sequence_container_traits<Type>::clear},
+          begin_fn{&meta_sequence_container_traits<Type>::begin},
+          end_fn{&meta_sequence_container_traits<Type>::end},
+          insert_fn{&meta_sequence_container_traits<Type>::insert},
+          erase_fn{&meta_sequence_container_traits<Type>::erase},
+          get_fn{&meta_sequence_container_traits<Type>::get},
           storage{std::move(instance)}
           storage{std::move(instance)}
     {}
     {}
 
 
@@ -90,9 +87,6 @@ private:
 
 
 /*! @brief Proxy object for associative containers. */
 /*! @brief Proxy object for associative containers. */
 class meta_associative_container {
 class meta_associative_container {
-    template<typename>
-    struct meta_associative_container_proxy;
-
     class meta_iterator;
     class meta_iterator;
 
 
 public:
 public:
@@ -111,20 +105,20 @@ public:
      */
      */
     template<typename Type>
     template<typename Type>
     meta_associative_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
     meta_associative_container(std::in_place_type_t<Type>, any instance) ENTT_NOEXCEPT
-        : key_only_container{is_key_only_meta_associative_container_v<Type>},
+        : key_only_container{meta_associative_container_traits<Type>::key_only()},
           key_type_node{internal::meta_info<typename Type::key_type>::resolve()},
           key_type_node{internal::meta_info<typename Type::key_type>::resolve()},
           mapped_type_node{nullptr},
           mapped_type_node{nullptr},
           value_type_node{internal::meta_info<typename Type::value_type>::resolve()},
           value_type_node{internal::meta_info<typename Type::value_type>::resolve()},
-          size_fn{&meta_associative_container_proxy<Type>::size},
-          clear_fn{&meta_associative_container_proxy<Type>::clear},
-          begin_fn{&meta_associative_container_proxy<Type>::begin},
-          end_fn{&meta_associative_container_proxy<Type>::end},
-          insert_fn{&meta_associative_container_proxy<Type>::insert},
-          erase_fn{&meta_associative_container_proxy<Type>::erase},
-          find_fn{&meta_associative_container_proxy<Type>::find},
+          size_fn{&meta_associative_container_traits<Type>::size},
+          clear_fn{&meta_associative_container_traits<Type>::clear},
+          begin_fn{&meta_associative_container_traits<Type>::begin},
+          end_fn{&meta_associative_container_traits<Type>::end},
+          insert_fn{&meta_associative_container_traits<Type>::insert},
+          erase_fn{&meta_associative_container_traits<Type>::erase},
+          find_fn{&meta_associative_container_traits<Type>::find},
           storage{std::move(instance)}
           storage{std::move(instance)}
     {
     {
-        if constexpr(!is_key_only_meta_associative_container_v<Type>) {
+        if constexpr(!meta_associative_container_traits<Type>::key_only()) {
             mapped_type_node = internal::meta_info<typename Type::mapped_type>::resolve();
             mapped_type_node = internal::meta_info<typename Type::mapped_type>::resolve();
         }
         }
     }
     }
@@ -1682,9 +1676,6 @@ bool meta_any::set(const id_type id, Type &&value) {
 
 
 /*! @brief Opaque iterator for sequence containers. */
 /*! @brief Opaque iterator for sequence containers. */
 class meta_sequence_container::meta_iterator {
 class meta_sequence_container::meta_iterator {
-    /*! @brief A sequence container can access the underlying iterator. */
-    friend class meta_sequence_container;
-
     enum class operation { INCR, DEREF };
     enum class operation { INCR, DEREF };
 
 
     using vtable_type = void(const operation, const any &, void *);
     using vtable_type = void(const operation, const any &, void *);
@@ -1774,78 +1765,20 @@ public:
         return static_cast<bool>(handle);
         return static_cast<bool>(handle);
     }
     }
 
 
+    /**
+     * @brief Returns the underlying iterator.
+     * @return The underlying iterator.
+     */
+    any base() const ENTT_NOEXCEPT {
+        return handle.as_ref();
+    }
+
 private:
 private:
     vtable_type *vtable{};
     vtable_type *vtable{};
     any handle{};
     any handle{};
 };
 };
 
 
 
 
-template<typename Type>
-struct meta_sequence_container::meta_sequence_container_proxy {
-    using traits_type = meta_sequence_container_traits<Type>;
-
-    [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
-        return traits_type::size(any_cast<const Type &>(container));
-    }
-
-    [[nodiscard]] static bool resize(any &container, size_type sz) {
-        auto * const cont = any_cast<Type>(&container);
-        return cont && traits_type::resize(*cont, sz);
-    }
-
-    [[nodiscard]] static bool clear(any &container) {
-        auto * const cont = any_cast<Type>(&container);
-        return cont && traits_type::clear(*cont);
-    }
-
-    [[nodiscard]] static iterator begin(any &container) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            return iterator{traits_type::begin(*cont)};
-        }
-
-        return iterator{traits_type::cbegin(any_cast<const Type &>(container))};
-    }
-
-    [[nodiscard]] static iterator end(any &container) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            return iterator{traits_type::end(*cont)};
-        }
-
-        return iterator{traits_type::cend(any_cast<const Type &>(container))};
-    }
-
-    [[nodiscard]] static std::pair<iterator, bool> insert(any &container, iterator it, meta_any &value) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
-            if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
-                const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
-                auto ret = traits_type::insert(*cont, any_cast<const typename Type::iterator &>(it.handle), element ? *element : value.cast<typename Type::value_type>());
-                return { iterator{std::move(ret.first)}, ret.second };
-            }
-        }
-
-        return {};
-    }
-
-    [[nodiscard]] static std::pair<iterator, bool> erase(any &container, iterator it) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            auto ret = traits_type::erase(*cont, any_cast<const typename Type::iterator &>(it.handle));
-            return { iterator{std::move(ret.first)}, ret.second };
-        }
-
-        return {};
-    }
-
-    [[nodiscard]] static meta_any get(any &container, size_type pos) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            return meta_any{std::in_place_type<typename Type::reference>, traits_type::get(*cont, pos)};
-        }
-
-        return meta_any{std::in_place_type<typename Type::const_reference>, traits_type::cget(any_cast<const Type &>(container), pos)};
-    }
-};
-
-
 /**
 /**
  * @brief Returns the meta value type of a container.
  * @brief Returns the meta value type of a container.
  * @return The meta value type of the container.
  * @return The meta value type of the container.
@@ -1946,7 +1879,7 @@ inline std::pair<meta_sequence_container::iterator, bool> meta_sequence_containe
 
 
 /*! @brief Opaque iterator for associative containers. */
 /*! @brief Opaque iterator for associative containers. */
 class meta_associative_container::meta_iterator {
 class meta_associative_container::meta_iterator {
-    enum operation { INCR, DEREF };
+    enum class operation { INCR, DEREF };
 
 
     using vtable_type = void(const operation, const any &, void *);
     using vtable_type = void(const operation, const any &, void *);
 
 
@@ -2048,70 +1981,6 @@ private:
 };
 };
 
 
 
 
-template<typename Type>
-struct meta_associative_container::meta_associative_container_proxy {
-    using traits_type = meta_associative_container_traits<Type>;
-
-    [[nodiscard]] static size_type size(const any &container) ENTT_NOEXCEPT {
-        return traits_type::size(any_cast<const Type &>(container));
-    }
-
-    [[nodiscard]] static bool clear(any &container) {
-        auto * const cont = any_cast<Type>(&container);
-        return cont && traits_type::clear(*cont);
-    }
-
-    [[nodiscard]] static iterator begin(any &container) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(*cont)};
-        }
-
-        return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cbegin(any_cast<const Type &>(container))};
-    }
-
-    [[nodiscard]] static iterator end(any &container) {
-        if(auto * const cont = any_cast<Type>(&container); cont) {
-            return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(*cont)};
-        }
-
-        return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cend(any_cast<const Type &>(container))};
-    }
-
-    [[nodiscard]] static bool insert(any &container, meta_any &key, meta_any &value) {
-        if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
-            if constexpr(is_key_only_meta_associative_container_v<Type>) {
-                return traits_type::insert(*cont, key.cast<const typename Type::key_type &>());
-            } else {
-                return value.allow_cast<const typename Type::mapped_type &>()
-                    && traits_type::insert(*cont, key.cast<const typename Type::key_type &>(), value.cast<const typename Type::mapped_type &>());
-            }
-        }
-
-        return false;
-    }
-
-    [[nodiscard]] static bool erase(any &container, meta_any &key) {
-        if(auto * const cont = any_cast<Type>(&container); cont && key.allow_cast<const typename Type::key_type &>()) {
-            return traits_type::erase(*cont, key.cast<const typename Type::key_type &>());
-        }
-
-        return false;
-    }
-
-    [[nodiscard]] static iterator find(any &container, meta_any &key) {
-        if(key.allow_cast<const typename Type::key_type &>()) {
-            if(auto * const cont = any_cast<Type>(&container); cont) {
-                return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::find(*cont, key.cast<const typename Type::key_type &>())};
-            }
-
-            return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::cfind(any_cast<const Type &>(container), key.cast<const typename Type::key_type &>())};
-        }
-
-        return {};
-    }
-};
-
-
 /**
 /**
  * @brief Returns true if a container is also key-only, false otherwise.
  * @brief Returns true if a container is also key-only, false otherwise.
  * @return True if the associative container is also key-only, false otherwise.
  * @return True if the associative container is also key-only, false otherwise.

+ 0 - 24
src/entt/meta/type_traits.hpp

@@ -33,30 +33,6 @@ template<typename>
 struct meta_associative_container_traits;
 struct meta_associative_container_traits;
 
 
 
 
-/**
- * @brief Provides the member constant `value` to true if a meta associative
- * container claims to wrap a key-only type, false otherwise.
- * @tparam Type Potentially key-only meta associative container type.
- */
-template<typename, typename = void>
-struct is_key_only_meta_associative_container: std::true_type {};
-
-
-/*! @copydoc is_key_only_meta_associative_container */
-template<typename Type>
-struct is_key_only_meta_associative_container<Type, std::void_t<decltype(meta_associative_container_traits<Type>::insert(std::declval<Type>(), {}, {}))>>
-    : std::false_type
-{};
-
-
-/**
- * @brief Helper variable template.
- * @tparam Type Potentially key-only meta associative container type.
- */
-template<typename Type>
-inline constexpr auto is_key_only_meta_associative_container_v = is_key_only_meta_associative_container<Type>::value;
-
-
 /**
 /**
  * @brief Provides the member constant `value` to true if a given type is a
  * @brief Provides the member constant `value` to true if a given type is a
  * pointer-like type from the point of view of the meta system, false otherwise.
  * pointer-like type from the point of view of the meta system, false otherwise.

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

@@ -256,9 +256,11 @@ TEST_F(MetaType, Traits) {
     ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_pointer_like());
     ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_pointer_like());
     ASSERT_FALSE(entt::resolve<int>().is_pointer_like());
     ASSERT_FALSE(entt::resolve<int>().is_pointer_like());
 
 
+    ASSERT_FALSE((entt::resolve<int>().is_sequence_container()));
     ASSERT_TRUE(entt::resolve<std::vector<int>>().is_sequence_container());
     ASSERT_TRUE(entt::resolve<std::vector<int>>().is_sequence_container());
     ASSERT_FALSE((entt::resolve<std::map<int, char>>().is_sequence_container()));
     ASSERT_FALSE((entt::resolve<std::map<int, char>>().is_sequence_container()));
 
 
+    ASSERT_FALSE((entt::resolve<int>().is_associative_container()));
     ASSERT_TRUE((entt::resolve<std::map<int, char>>().is_associative_container()));
     ASSERT_TRUE((entt::resolve<std::map<int, char>>().is_associative_container()));
     ASSERT_FALSE(entt::resolve<std::vector<int>>().is_associative_container());
     ASSERT_FALSE(entt::resolve<std::vector<int>>().is_associative_container());