diff --git a/src/entt/entity/view.hpp b/src/entt/entity/view.hpp index 4139e2ade..e3b32b3fc 100644 --- a/src/entt/entity/view.hpp +++ b/src/entt/entity/view.hpp @@ -30,6 +30,86 @@ namespace entt { namespace internal { +template +class iterable_storage final { + using basic_common_type = basic_sparse_set; + using storage_type = constness_as_t>::storage_type, Component>; + + template + struct iterable_storage_iterator final { + using difference_type = std::ptrdiff_t; + using value_type = decltype(std::tuple_cat(std::tuple{}, std::declval(), {}))>())); + using pointer = void; + using reference = value_type; + using iterator_category = std::input_iterator_tag; + + template + iterable_storage_iterator(It... from, Discard...) ENTT_NOEXCEPT + : it{from...} + {} + + iterable_storage_iterator & operator++() ENTT_NOEXCEPT { + return (++std::get(it), ...), *this; + } + + iterable_storage_iterator operator++(int) ENTT_NOEXCEPT { + iterable_storage_iterator orig = *this; + return ++(*this), orig; + } + + [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { + return { *std::get(it)... }; + } + + [[nodiscard]] bool operator==(const iterable_storage_iterator &other) const ENTT_NOEXCEPT { + return std::get<0>(other.it) == std::get<0>(it); + } + + [[nodiscard]] bool operator!=(const iterable_storage_iterator &other) const ENTT_NOEXCEPT { + return !(*this == other); + } + + private: + std::tuple it; + }; + +public: + using iterator = std::conditional_t< + std::is_void_v().get({}))>, + iterable_storage_iterator, + iterable_storage_iterator().begin())> + >; + using reverse_iterator = std::conditional_t< + std::is_void_v().get({}))>, + iterable_storage_iterator, + iterable_storage_iterator().rbegin())> + >; + + iterable_storage(storage_type &ref) + : pool{&ref} + {} + + [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { + return iterator{pool->basic_common_type::begin(), pool->begin()}; + } + + [[nodiscard]] iterator end() const ENTT_NOEXCEPT { + return iterator{pool->basic_common_type::end(), pool->end()}; + } + + [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { + return reverse_iterator{pool->basic_common_type::rbegin(), pool->rbegin()}; + } + + [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { + return reverse_iterator{pool->basic_common_type::rend(), pool->rend()}; + } + +private: + storage_type * const pool; +}; + + template class view_iterator final { using basic_common_type = basic_sparse_set::value_type>; @@ -281,45 +361,27 @@ class basic_view_impl, Component...> { return other; } - template - [[nodiscard]] auto dispatch_get([[maybe_unused]] It &it, [[maybe_unused]] const Entity entt) const { - if constexpr(std::is_same_v::value_type, typename storage_type::value_type>) { - return std::forward_as_tuple(*it); + template + [[nodiscard]] auto dispatch_get(const std::tuple &curr) const { + if constexpr(std::is_same_v) { + return std::forward_as_tuple(std::get(curr)...); } else { - return get_as_tuple(*std::get *>(pools), entt); + return get_as_tuple(*std::get *>(pools), std::get<0>(curr)); } } template void traverse(Func func) const { - if constexpr(std::is_void_v *>(pools)->get({}))>) { - for(const auto entt: static_cast(*std::get *>(pools))) { - if(Policy::accept(entt) && ((std::is_same_v || std::get *>(pools)->contains(entt)) && ...) - && std::apply([entt](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter)) - { - if constexpr(is_applicable_v{}, std::declval().get({})))>) { - std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt))); - } else { - std::apply(func, get(entt)); - } + for(const auto curr: internal::iterable_storage{*std::get *>(pools)}) { + if(Policy::accept(std::get<0>(curr)) && ((std::is_same_v || std::get *>(pools)->contains(std::get<0>(curr))) && ...) + && std::apply([entt = std::get<0>(curr)](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter)) + { + if constexpr(is_applicable_v{}, std::declval().get({})))>) { + std::apply(func, std::tuple_cat(std::make_tuple(std::get<0>(curr)), dispatch_get(curr)...)); + } else { + std::apply(func, std::tuple_cat(dispatch_get(curr)...)); } } - } else { - auto it = std::get *>(pools)->begin(); - - for(const auto entt: static_cast(*std::get *>(pools))) { - if(Policy::accept(entt) && ((std::is_same_v || std::get *>(pools)->contains(entt)) && ...) - && std::apply([entt](const auto *... curr) { return (!curr->contains(entt) && ...); }, filter)) - { - if constexpr(is_applicable_v{}, std::declval().get({})))>) { - std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get(it, entt)...)); - } else { - std::apply(func, std::tuple_cat(dispatch_get(it, entt)...)); - } - } - - ++it; - } } } @@ -634,81 +696,6 @@ class basic_view_impl, Component> { using basic_common_type = basic_sparse_set; using storage_type = constness_as_t>::storage_type, Component>; - class iterable final { - template - struct iterable_iterator final { - using difference_type = std::ptrdiff_t; - using value_type = decltype(std::tuple_cat(std::tuple{}, std::declval().get({}))); - using pointer = void; - using reference = value_type; - using iterator_category = std::input_iterator_tag; - - template - iterable_iterator(It... from, Discard...) ENTT_NOEXCEPT - : it{from...} - {} - - iterable_iterator & operator++() ENTT_NOEXCEPT { - return (++std::get(it), ...), *this; - } - - iterable_iterator operator++(int) ENTT_NOEXCEPT { - iterable_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const ENTT_NOEXCEPT { - return { *std::get(it)... }; - } - - [[nodiscard]] bool operator==(const iterable_iterator &other) const ENTT_NOEXCEPT { - return std::get<0>(other.it) == std::get<0>(it); - } - - [[nodiscard]] bool operator!=(const iterable_iterator &other) const ENTT_NOEXCEPT { - return !(*this == other); - } - - private: - std::tuple it; - }; - - public: - using iterator = std::conditional_t< - std::is_void_v().get({}))>, - iterable_iterator, - iterable_iterator().begin())> - >; - using reverse_iterator = std::conditional_t< - std::is_void_v().get({}))>, - iterable_iterator, - iterable_iterator().rbegin())> - >; - - iterable(storage_type &ref) - : pool{&ref} - {} - - [[nodiscard]] iterator begin() const ENTT_NOEXCEPT { - return iterator{pool->basic_common_type::begin(), pool->begin()}; - } - - [[nodiscard]] iterator end() const ENTT_NOEXCEPT { - return iterator{pool->basic_common_type::end(), pool->end()}; - } - - [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT { - return reverse_iterator{pool->basic_common_type::rbegin(), pool->rbegin()}; - } - - [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT { - return reverse_iterator{pool->basic_common_type::rend(), pool->rend()}; - } - - private: - storage_type * const pool; - }; - public: /*! @brief Underlying entity identifier. */ using entity_type = Entity; @@ -719,7 +706,7 @@ public: /*! @brief Reversed iterator type. */ using reverse_iterator = typename basic_common_type::reverse_iterator; /*! @brief Iterable view type. */ - using iterable_view = iterable; + using iterable_view = internal::iterable_storage; /*! @brief Default constructor to use to create empty, invalid views. */ basic_view_impl() ENTT_NOEXCEPT