#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 * Internal details not to be documented. */ namespace internal { template struct is_dynamic_sequence_container: std::false_type {}; template struct is_dynamic_sequence_container>: std::true_type {}; template struct is_key_only_meta_associative_container: std::true_type {}; template struct is_key_only_meta_associative_container>: std::false_type {}; template 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) noexcept { return any_cast(container).size(); } [[nodiscard]] static bool resize([[maybe_unused]] any &container, [[maybe_unused]] size_type sz) { if constexpr(is_dynamic_sequence_container::value) { if(auto *const cont = any_cast(&container); cont) { cont->resize(sz); return true; } } return false; } [[nodiscard]] static iterator iter(const meta_ctx &ctx, any &container, const bool as_end) { if(auto *const cont = any_cast(&container); cont) { return iterator{ctx, as_end ? cont->end() : cont->begin()}; } const Type &as_const = any_cast(container); return iterator{ctx, as_end ? as_const.end() : as_const.begin()}; } [[nodiscard]] static iterator insert_or_erase([[maybe_unused]] const meta_ctx &ctx, [[maybe_unused]] any &container, [[maybe_unused]] const any &handle, [[maybe_unused]] meta_any &value) { if constexpr(is_dynamic_sequence_container::value) { if(auto *const cont = any_cast(&container); cont) { typename Type::const_iterator it{}; if(auto *non_const = any_cast(&handle); non_const) { it = *non_const; } else { it = any_cast(handle); } if(value) { // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector if(value.allow_cast() || value.allow_cast()) { const auto *element = value.try_cast>(); return iterator{ctx, cont->insert(it, element ? *element : value.cast())}; } } else { return iterator{ctx, cont->erase(it)}; } } } return iterator{}; } }; template struct basic_meta_associative_container_traits { using iterator = meta_associative_container::iterator; using size_type = std::size_t; static constexpr auto key_only = is_key_only_meta_associative_container::value; [[nodiscard]] static size_type size(const any &container) noexcept { return any_cast(container).size(); } [[nodiscard]] static bool clear(any &container) { if(auto *const cont = any_cast(&container); cont) { cont->clear(); return true; } return false; } [[nodiscard]] static iterator iter(const meta_ctx &ctx, any &container, const bool as_end) { if(auto *const cont = any_cast(&container); cont) { return iterator{ctx, std::bool_constant{}, as_end ? cont->end() : cont->begin()}; } const auto &as_const = any_cast(container); return iterator{ctx, std::bool_constant{}, as_end ? as_const.end() : as_const.begin()}; } [[nodiscard]] static size_type insert_or_erase(any &container, meta_any &key, meta_any &value) { if(auto *const cont = any_cast(&container); cont && key.allow_cast()) { if(value) { if constexpr(key_only) { return cont->insert(key.cast()).second; } else { return value.allow_cast() && cont->emplace(key.cast(), value.cast()).second; } } else { return cont->erase(key.cast()); } } return 0u; } [[nodiscard]] static iterator find(const meta_ctx &ctx, any &container, meta_any &key) { if(key.allow_cast()) { if(auto *const cont = any_cast(&container); cont) { return iterator{ctx, std::bool_constant{}, cont->find(key.cast())}; } return iterator{ctx, std::bool_constant{}, any_cast(container).find(key.cast())}; } return iterator{}; } }; } // namespace internal /** * Internal details not to be documented. * @endcond */ /** * @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> : internal::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> : internal::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> : internal::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> : internal::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> : internal::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> : internal::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> : internal::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> : internal::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> : internal::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> : internal::basic_meta_associative_container_traits> {}; } // namespace entt #endif