Browse Source

sparse_set: scoped iterator

Michele Caini 2 years ago
parent
commit
361d4ec4dd
2 changed files with 181 additions and 0 deletions
  1. 40 0
      src/entt/entity/sparse_set.hpp
  2. 141 0
      test/entt/entity/sparse_set.cpp

+ 40 - 0
src/entt/entity/sparse_set.hpp

@@ -666,6 +666,46 @@ public:
         return rend();
     }
 
+    /*! @copydoc begin Useful only in case of swap-only policy. */
+    [[nodiscard]] iterator begin(int) const noexcept {
+        return begin() + static_cast<typename iterator::difference_type>((size() - static_cast<size_type>(head)) * (mode == deletion_policy::swap_only));
+    }
+
+    /*! @copydoc cbegin Useful only in case of swap-only policy. */
+    [[nodiscard]] const_iterator cbegin(int) const noexcept {
+        return begin(0);
+    }
+
+    /*! @copydoc end Useful only in case of swap-only policy. */
+    [[nodiscard]] iterator end(int) const noexcept {
+        return end();
+    }
+
+    /*! @copydoc cend Useful only in case of swap-only policy. */
+    [[nodiscard]] const_iterator cend(int) const noexcept {
+        return end(0);
+    }
+
+    /*! @copydoc rbegin Useful only in case of swap-only policy. */
+    [[nodiscard]] reverse_iterator rbegin(int) const noexcept {
+        return std::make_reverse_iterator(end(0));
+    }
+
+    /*! @copydoc rbegin Useful only in case of swap-only policy. */
+    [[nodiscard]] const_reverse_iterator crbegin(int) const noexcept {
+        return rbegin(0);
+    }
+
+    /*! @copydoc rbegin Useful only in case of swap-only policy. */
+    [[nodiscard]] reverse_iterator rend(int) const noexcept {
+        return std::make_reverse_iterator(begin(0));
+    }
+
+    /*! @copydoc rbegin Useful only in case of swap-only policy. */
+    [[nodiscard]] const_reverse_iterator crend(int) const noexcept {
+        return rend(0);
+    }
+
     /**
      * @brief Finds an entity.
      * @param entt A valid identifier.

+ 141 - 0
test/entt/entity/sparse_set.cpp

@@ -1271,6 +1271,80 @@ TEST(SparseSet, Iterator) {
     ASSERT_EQ(begin[1u], entt::entity{3});
 }
 
+TEST(SparseSet, ScopedIterator) {
+    using iterator = typename entt::sparse_set::iterator;
+
+    testing::StaticAssertTypeEq<iterator::value_type, entt::entity>();
+    testing::StaticAssertTypeEq<iterator::pointer, const entt::entity *>();
+    testing::StaticAssertTypeEq<iterator::reference, const entt::entity &>();
+
+    entt::sparse_set set{entt::deletion_policy::swap_only};
+    entt::entity entity[2u]{entt::entity{3}, entt::entity{7}};
+
+    set.push(std::begin(entity), std::end(entity));
+    set.erase(entity[1u]);
+
+    iterator end{set.begin(0)};
+    iterator begin{};
+
+    ASSERT_EQ(end.data(), set.data());
+    ASSERT_EQ(begin.data(), nullptr);
+
+    begin = set.end(0);
+    std::swap(begin, end);
+
+    ASSERT_EQ(end.data(), set.data());
+    ASSERT_EQ(begin.data(), set.data());
+
+    ASSERT_EQ(begin, set.cbegin(0));
+    ASSERT_EQ(end, set.cend(0));
+    ASSERT_NE(begin, end);
+
+    ASSERT_EQ(begin.index(), 0);
+    ASSERT_EQ(end.index(), -1);
+
+    ASSERT_EQ(begin++, set.begin(0));
+    ASSERT_EQ(begin--, set.end(0));
+
+    ASSERT_EQ(begin + 1, set.end(0));
+    ASSERT_EQ(end - 1, set.begin(0));
+
+    ASSERT_EQ(++begin, set.end(0));
+    ASSERT_EQ(--begin, set.begin(0));
+
+    ASSERT_EQ(begin += 1, set.end(0));
+    ASSERT_EQ(begin -= 1, set.begin(0));
+
+    ASSERT_EQ(begin + (end - begin), set.end(0));
+    ASSERT_EQ(begin - (begin - end), set.end(0));
+
+    ASSERT_EQ(end - (end - begin), set.begin(0));
+    ASSERT_EQ(end + (begin - end), set.begin(0));
+
+    ASSERT_EQ(begin[0u], *set.begin(0));
+
+    ASSERT_LT(begin, end);
+    ASSERT_LE(begin, set.begin(0));
+
+    ASSERT_GT(end, begin);
+    ASSERT_GE(end, set.end(0));
+
+    ASSERT_EQ(*begin, entt::entity{3});
+    ASSERT_EQ(*begin.operator->(), entt::entity{3});
+
+    ASSERT_EQ(begin.index(), 0);
+    ASSERT_EQ(end.index(), -1);
+
+    set.push(entt::entity{42});
+    begin = set.begin(0);
+
+    ASSERT_EQ(begin.index(), 1);
+    ASSERT_EQ(end.index(), -1);
+
+    ASSERT_EQ(begin[0u], entt::entity{42});
+    ASSERT_EQ(begin[1u], entt::entity{3});
+}
+
 TEST(SparseSet, ReverseIterator) {
     using reverse_iterator = typename entt::sparse_set::reverse_iterator;
 
@@ -1335,6 +1409,73 @@ TEST(SparseSet, ReverseIterator) {
     ASSERT_EQ(begin[1u], entt::entity{42});
 }
 
+TEST(SparseSet, ScopedReverseIterator) {
+    using reverse_iterator = typename entt::sparse_set::reverse_iterator;
+
+    testing::StaticAssertTypeEq<reverse_iterator::value_type, entt::entity>();
+    testing::StaticAssertTypeEq<reverse_iterator::pointer, const entt::entity *>();
+    testing::StaticAssertTypeEq<reverse_iterator::reference, const entt::entity &>();
+
+    entt::sparse_set set{entt::deletion_policy::swap_only};
+    entt::entity entity[2u]{entt::entity{3}, entt::entity{7}};
+
+    set.push(std::begin(entity), std::end(entity));
+    set.erase(entity[1u]);
+
+    reverse_iterator end{set.rbegin(0)};
+    reverse_iterator begin{};
+    begin = set.rend(0);
+    std::swap(begin, end);
+
+    ASSERT_EQ(begin, set.crbegin(0));
+    ASSERT_EQ(end, set.crend(0));
+    ASSERT_NE(begin, end);
+
+    ASSERT_EQ(begin.base().index(), -1);
+    ASSERT_EQ(end.base().index(), 0);
+
+    ASSERT_EQ(begin++, set.rbegin(0));
+    ASSERT_EQ(begin--, set.rend(0));
+
+    ASSERT_EQ(begin + 1, set.rend(0));
+    ASSERT_EQ(end - 1, set.rbegin(0));
+
+    ASSERT_EQ(++begin, set.rend(0));
+    ASSERT_EQ(--begin, set.rbegin(0));
+
+    ASSERT_EQ(begin += 1, set.rend(0));
+    ASSERT_EQ(begin -= 1, set.rbegin(0));
+
+    ASSERT_EQ(begin + (end - begin), set.rend(0));
+    ASSERT_EQ(begin - (begin - end), set.rend(0));
+
+    ASSERT_EQ(end - (end - begin), set.rbegin(0));
+    ASSERT_EQ(end + (begin - end), set.rbegin(0));
+
+    ASSERT_EQ(begin[0u], *set.rbegin(0));
+
+    ASSERT_LT(begin, end);
+    ASSERT_LE(begin, set.rbegin(0));
+
+    ASSERT_GT(end, begin);
+    ASSERT_GE(end, set.rend(0));
+
+    ASSERT_EQ(*begin, entt::entity{3});
+    ASSERT_EQ(*begin.operator->(), entt::entity{3});
+
+    ASSERT_EQ(begin.base().index(), -1);
+    ASSERT_EQ(end.base().index(), 0);
+
+    set.push(entt::entity{42});
+    end = set.rend(0);
+
+    ASSERT_EQ(begin.base().index(), -1);
+    ASSERT_EQ(end.base().index(), 1);
+
+    ASSERT_EQ(begin[0u], entt::entity{3});
+    ASSERT_EQ(begin[1u], entt::entity{42});
+}
+
 TEST(SparseSet, Find) {
     using traits_type = entt::entt_traits<entt::entity>;