// IWYU pragma: always_keep #ifndef ENTT_META_CONTAINER_HPP #define ENTT_META_CONTAINER_HPP #include #include #include #include #include #include #include #include #include #include #include "../container/dense_map.hpp" #include "../container/dense_set.hpp" #include "context.hpp" #include "meta.hpp" #include "type_traits.hpp" namespace entt { /*! @cond TURN_OFF_DOXYGEN */ namespace internal { template struct fixed_size_sequence_container: std::true_type {}; template struct fixed_size_sequence_container>: std::false_type {}; template inline constexpr bool fixed_size_sequence_container_v = fixed_size_sequence_container::value; template struct key_only_associative_container: std::true_type {}; template struct key_only_associative_container>: std::false_type {}; template inline constexpr bool key_only_associative_container_v = key_only_associative_container::value; template struct reserve_aware_container: std::false_type {}; template struct reserve_aware_container>: std::true_type {}; template inline constexpr bool reserve_aware_container_v = reserve_aware_container::value; } // namespace internal /*! @endcond */ /** * @brief General purpose implementation of meta sequence container traits. * @tparam Type Type of underlying sequence container. */ template struct basic_meta_sequence_container_traits { static_assert(std::is_same_v>>, "Unexpected type"); /*! @brief Unsigned integer type. */ using size_type = typename meta_sequence_container::size_type; /*! @brief Meta iterator type. */ using iterator = typename meta_sequence_container::iterator; /*! @brief True in case of key-only containers, false otherwise. */ static constexpr bool fixed_size = internal::fixed_size_sequence_container_v; /** * @brief Returns the number of elements in a container. * @param container Opaque pointer to a container of the given type. * @return Number of elements. */ [[nodiscard]] static size_type size(const void *container) { return static_cast(container)->size(); } /** * @brief Clears a container. * @param container Opaque pointer to a container of the given type. * @return True in case of success, false otherwise. */ [[nodiscard]] static bool clear([[maybe_unused]] void *container) { if constexpr(fixed_size) { return false; } else { static_cast(container)->clear(); return true; } } /** * @brief Increases the capacity of a container. * @param container Opaque pointer to a container of the given type. * @param sz Desired capacity. * @return True in case of success, false otherwise. */ [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { if constexpr(internal::reserve_aware_container_v) { static_cast(container)->reserve(sz); return true; } else { return false; } } /** * @brief Resizes a container. * @param container Opaque pointer to a container of the given type. * @param sz The new number of elements. * @return True in case of success, false otherwise. */ [[nodiscard]] static bool resize([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { if constexpr(fixed_size || !std::is_default_constructible_v) { return false; } else { static_cast(container)->resize(sz); return true; } } /** * @brief Returns a possibly const iterator to the beginning. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param as_const Const opaque pointer fallback. * @return An iterator to the first element of the container. */ static iterator begin(const meta_ctx &area, void *container, const void *as_const) { return container ? iterator{area, static_cast(container)->begin()} : iterator{area, static_cast(as_const)->begin()}; } /** * @brief Returns a possibly const iterator to the end. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param as_const Const opaque pointer fallback. * @return An iterator that is past the last element of the container. */ static iterator end(const meta_ctx &area, void *container, const void *as_const) { return container ? iterator{area, static_cast(container)->end()} : iterator{area, static_cast(as_const)->end()}; } /** * @brief Assigns one element to a container and constructs its object from * a given opaque instance. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param value Optional opaque instance of the object to construct (as * value type). * @param cref Optional opaque instance of the object to construct (as * decayed const reference type). * @param it Iterator before which the element will be inserted. * @return A possibly invalid iterator to the inserted element. */ [[nodiscard]] static iterator insert([[maybe_unused]] const meta_ctx &area, [[maybe_unused]] void *container, [[maybe_unused]] const void *value, [[maybe_unused]] const void *cref, [[maybe_unused]] const iterator &it) { if constexpr(fixed_size) { return iterator{}; } else { auto *const non_const = any_cast(&it.base()); return {area, static_cast(container)->insert( non_const ? *non_const : any_cast(it.base()), value ? *static_cast(value) : *static_cast *>(cref))}; } } /** * @brief Erases an element from a container. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param it An opaque iterator to the element to erase. * @return A possibly invalid iterator following the last removed element. */ [[nodiscard]] static iterator erase([[maybe_unused]] const meta_ctx &area, [[maybe_unused]] void *container, [[maybe_unused]] const iterator &it) { if constexpr(fixed_size) { return iterator{}; } else { auto *const non_const = any_cast(&it.base()); return {area, static_cast(container)->erase(non_const ? *non_const : any_cast(it.base()))}; } } }; /** * @brief General purpose implementation of meta associative container traits. * @tparam Type Type of underlying associative container. */ template struct basic_meta_associative_container_traits { static_assert(std::is_same_v>>, "Unexpected type"); /*! @brief Unsigned integer type. */ using size_type = typename meta_associative_container::size_type; /*! @brief Meta iterator type. */ using iterator = typename meta_associative_container::iterator; /*! @brief True in case of key-only containers, false otherwise. */ static constexpr bool key_only = internal::key_only_associative_container_v; /** * @brief Returns the number of elements in a container. * @param container Opaque pointer to a container of the given type. * @return Number of elements. */ [[nodiscard]] static size_type size(const void *container) { return static_cast(container)->size(); } /** * @brief Clears a container. * @param container Opaque pointer to a container of the given type. * @return True in case of success, false otherwise. */ [[nodiscard]] static bool clear(void *container) { static_cast(container)->clear(); return true; } /** * @brief Increases the capacity of a container. * @param container Opaque pointer to a container of the given type. * @param sz Desired capacity. * @return True in case of success, false otherwise. */ [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { if constexpr(internal::reserve_aware_container_v) { static_cast(container)->reserve(sz); return true; } else { return false; } } /** * @brief Returns a possibly const iterator to the beginning. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param as_const Const opaque pointer fallback. * @return An iterator to the first element of the container. */ static iterator begin(const meta_ctx &area, void *container, const void *as_const) { return container ? iterator{area, std::bool_constant{}, static_cast(container)->begin()} : iterator{area, std::bool_constant{}, static_cast(as_const)->begin()}; } /** * @brief Returns a possibly const iterator to the end. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param as_const Const opaque pointer fallback. * @return An iterator that is past the last element of the container. */ static iterator end(const meta_ctx &area, void *container, const void *as_const) { return container ? iterator{area, std::bool_constant{}, static_cast(container)->end()} : iterator{area, std::bool_constant{}, static_cast(as_const)->end()}; } /** * @brief Inserts an element into a container, if the key does not exist. * @param container Opaque pointer to a container of the given type. * @param key An opaque key value of an element to insert. * @param value Optional opaque value to insert (key-value containers). * @return True if the insertion took place, false otherwise. */ [[nodiscard]] static bool insert(void *container, const void *key, [[maybe_unused]] const void *value) { if constexpr(key_only) { return static_cast(container)->insert(*static_cast(key)).second; } else { return static_cast(container)->emplace(*static_cast(key), *static_cast(value)).second; } } /** * @brief Removes an element from a container. * @param container Opaque pointer to a container of the given type. * @param key An opaque key value of an element to remove. * @return Number of elements removed (either 0 or 1). */ [[nodiscard]] static size_type erase(void *container, const void *key) { return static_cast(container)->erase(*static_cast(key)); } /** * @brief Finds an element with a given key. * @param area The context to pass to the newly created iterator. * @param container Opaque pointer to a container of the given type. * @param as_const Const opaque pointer fallback. * @param key Opaque key value of an element to search for. * @return An iterator to the element with the given key, if any. */ static iterator find(const meta_ctx &area, void *container, const void *as_const, const void *key) { return container ? iterator{area, std::bool_constant{}, static_cast(container)->find(*static_cast(key))} : iterator{area, std::bool_constant{}, static_cast(as_const)->find(*static_cast(key))}; } }; /** * @brief Meta sequence container traits for `std::vector`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_sequence_container_traits> : basic_meta_sequence_container_traits> {}; /** * @brief Meta sequence container traits for `std::array`s of any type. * @tparam Type Template arguments for the container. * @tparam N Template arguments for the container. */ template struct meta_sequence_container_traits> : basic_meta_sequence_container_traits> {}; /** * @brief Meta sequence container traits for `std::list`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_sequence_container_traits> : basic_meta_sequence_container_traits> {}; /** * @brief Meta sequence container traits for `std::deque`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_sequence_container_traits> : basic_meta_sequence_container_traits> {}; /** * @brief Meta associative container traits for `std::map`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_associative_container_traits> : basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `std::unordered_map`s of any * type. * @tparam Args Template arguments for the container. */ template struct meta_associative_container_traits> : basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `std::set`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_associative_container_traits> : basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `std::unordered_set`s of any * type. * @tparam Args Template arguments for the container. */ template struct meta_associative_container_traits> : basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `dense_map`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_associative_container_traits> : basic_meta_associative_container_traits> {}; /** * @brief Meta associative container traits for `dense_set`s of any type. * @tparam Args Template arguments for the container. */ template struct meta_associative_container_traits> : basic_meta_associative_container_traits> {}; } // namespace entt #endif