diff --git a/src/entt/meta/container.hpp b/src/entt/meta/container.hpp index 2d532b9b9..d72c4b17e 100644 --- a/src/entt/meta/container.hpp +++ b/src/entt/meta/container.hpp @@ -3,20 +3,11 @@ #ifndef ENTT_META_CONTAINER_HPP #define ENTT_META_CONTAINER_HPP -#include #include #include -#include #include -#include -#include -#include #include -#include -#include -#include -#include "../container/dense_map.hpp" -#include "../container/dense_set.hpp" +#include #include "../core/concepts.hpp" #include "../core/type_traits.hpp" #include "context.hpp" @@ -39,15 +30,27 @@ struct sequence_container_extent: integral_constant inline constexpr std::size_t sequence_container_extent_v = sequence_container_extent::value; -template -struct key_only_associative_container: std::true_type {}; +template +concept meta_sequence_container_like = requires(Type elem) { + typename Type::value_type; + typename Type::iterator; + requires std::forward_iterator; + { elem.begin() } -> std::same_as; + { elem.end() } -> std::same_as; + requires !requires { typename Type::key_type; }; + requires !requires { elem.substr(); }; +}; template -requires requires { typename Type::mapped_type; } -struct key_only_associative_container: std::false_type {}; - -template -inline constexpr bool key_only_associative_container_v = key_only_associative_container::value; +concept meta_associative_container_like = requires(Type value) { + typename Type::key_type; + typename Type::value_type; + typename Type::iterator; + requires std::forward_iterator; + { value.begin() } -> std::same_as; + { value.end() } -> std::same_as; + value.find(std::declval()); +}; } // namespace internal /*! @endcond */ @@ -81,7 +84,7 @@ struct basic_meta_sequence_container_traits { * @return True in case of success, false otherwise. */ [[nodiscard]] static bool clear([[maybe_unused]] void *container) { - if constexpr(extent == meta_dynamic_extent) { + if constexpr(requires(Type elem) { elem.clear(); }) { static_cast(container)->clear(); return true; } else { @@ -96,7 +99,7 @@ struct basic_meta_sequence_container_traits { * @return True in case of success, false otherwise. */ [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { - if constexpr(requires(Type elem) { { elem.reserve(sz) }; }) { + if constexpr(requires(Type elem) { elem.reserve(sz); }) { static_cast(container)->reserve(sz); return true; } else { @@ -111,7 +114,7 @@ struct basic_meta_sequence_container_traits { * @return True in case of success, false otherwise. */ [[nodiscard]] static bool resize([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { - if constexpr((extent == meta_dynamic_extent) && std::is_default_constructible_v) { + if constexpr(std::is_default_constructible_v && requires(Type elem) { elem.resize(sz); }) { static_cast(container)->resize(sz); return true; } else { @@ -147,7 +150,7 @@ struct basic_meta_sequence_container_traits { * @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(extent == meta_dynamic_extent) { + if constexpr(requires(Type elem, typename Type::const_iterator it, Type::value_type instance) { elem.insert(it, instance); }) { auto *const non_const = any_cast(&it.base()); return {area, static_cast(container)->insert( non_const ? *non_const : any_cast(it.base()), @@ -165,7 +168,7 @@ struct basic_meta_sequence_container_traits { * @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(extent == meta_dynamic_extent) { + if constexpr(requires(Type elem, typename Type::const_iterator it) { elem.erase(it); }) { auto *const non_const = any_cast(&it.base()); return {area, static_cast(container)->erase(non_const ? *non_const : any_cast(it.base()))}; } else { @@ -186,7 +189,7 @@ struct basic_meta_associative_container_traits { using iterator = 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; + static constexpr bool key_only = !requires { typename Type::mapped_type; }; /** * @brief Returns the number of elements in a container. @@ -214,7 +217,7 @@ struct basic_meta_associative_container_traits { * @return True in case of success, false otherwise. */ [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { - if constexpr(requires(Type elem) { { elem.reserve(sz) }; }) { + if constexpr(requires(Type elem) { elem.reserve(sz); }) { static_cast(container)->reserve(sz); return true; } else { @@ -277,87 +280,18 @@ struct basic_meta_associative_container_traits { }; /** - * @brief Meta sequence container traits for `std::vector`s of any type. - * @tparam Args Template arguments for the container. + * @brief Traits meta sequence container like types. + * @tparam Type Container type to inspect. */ -template -struct meta_sequence_container_traits> - : basic_meta_sequence_container_traits> {}; +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. + * @brief Traits for meta associative container like types. + * @tparam Type Container type to inspect. */ -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> {}; +template +struct meta_associative_container_traits: basic_meta_associative_container_traits {}; } // namespace entt diff --git a/test/entt/meta/meta_container.cpp b/test/entt/meta/meta_container.cpp index 68799589d..6744e90f0 100644 --- a/test/entt/meta/meta_container.cpp +++ b/test/entt/meta/meta_container.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include #include @@ -63,6 +65,26 @@ TEST(SequenceContainer, Iterator) { ASSERT_EQ((--first)->cast(), 2); } +TEST(SequenceContainer, StdString) { + std::string str{}; + auto any = entt::forward_as_meta(str); + auto view = any.as_sequence_container(); + auto cview = std::as_const(any).as_sequence_container(); + + ASSERT_FALSE(view); + ASSERT_FALSE(cview); +} + +TEST(SequenceContainer, StdStringView) { + std::string_view str{}; + auto any = entt::forward_as_meta(str); + auto view = any.as_sequence_container(); + auto cview = std::as_const(any).as_sequence_container(); + + ASSERT_FALSE(view); + ASSERT_FALSE(cview); +} + TEST(SequenceContainer, StdVector) { std::vector vec{}; auto any = entt::forward_as_meta(vec);