Browse Source

sparse set: added reverse iterators

Michele Caini 5 years ago
parent
commit
75dd86e8ef
2 changed files with 74 additions and 8 deletions
  1. 30 8
      src/entt/entity/sparse_set.hpp
  2. 44 0
      test/entt/entity/sparse_set.cpp

+ 30 - 8
src/entt/entity/sparse_set.hpp

@@ -180,6 +180,8 @@ public:
     using size_type = std::size_t;
     /*! @brief Random access iterator type. */
     using iterator = sparse_set_iterator;
+    /*! @brief Reverse iterator type. */
+    using reverse_iterator = const entity_type *;
 
     /*! @brief Default constructor. */
     sparse_set() = default;
@@ -284,10 +286,6 @@ public:
      * array. If the sparse set is empty, the returned iterator will be equal to
      * `end()`.
      *
-     * @note
-     * Random access iterators stay true to the order imposed by a call to
-     * `respect`.
-     *
      * @return An iterator to the first entity of the internal packed array.
      */
     [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
@@ -302,10 +300,6 @@ public:
      * the internal packed array. Attempting to dereference the returned
      * iterator results in undefined behavior.
      *
-     * @note
-     * Random access iterators stay true to the order imposed by a call to
-     * `respect`.
-     *
      * @return An iterator to the element following the last entity of the
      * internal packed array.
      */
@@ -313,6 +307,34 @@ public:
         return iterator{packed, {}};
     }
 
+    /**
+     * @brief Returns a reverse iterator to the beginning.
+     *
+     * The returned iterator points to the first entity of the reversed internal
+     * packed array. If the sparse set is empty, the returned iterator will be
+     * equal to `rend()`.
+     *
+     * @return An iterator to the first entity of the reversed internal packed
+     * array.
+     */
+    [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
+        return packed.data();
+    }
+
+    /**
+     * @brief Returns a reverse iterator to the end.
+     *
+     * The returned iterator points to the element following the last entity in
+     * the reversed internal packed array. Attempting to dereference the
+     * returned iterator results in undefined behavior.
+     *
+     * @return An iterator to the element following the last entity of the
+     * reversed internal packed array.
+     */
+    [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
+        return rbegin() + packed.size();
+    }
+
     /**
      * @brief Finds an entity.
      * @param entt A valid entity identifier.

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

@@ -183,6 +183,50 @@ TEST(SparseSet, Iterator) {
     ASSERT_EQ(*begin.operator->(), entt::entity{3});
 }
 
+TEST(SparseSet, ReverseIterator) {
+    using reverse_iterator = typename entt::sparse_set<entt::entity>::reverse_iterator;
+
+    entt::sparse_set<entt::entity> set;
+    set.emplace(entt::entity{3});
+
+    reverse_iterator end{set.rbegin()};
+    reverse_iterator begin{};
+    begin = set.rend();
+    std::swap(begin, end);
+
+    ASSERT_EQ(begin, set.rbegin());
+    ASSERT_EQ(end, set.rend());
+    ASSERT_NE(begin, end);
+
+    ASSERT_EQ(begin++, set.rbegin());
+    ASSERT_EQ(begin--, set.rend());
+
+    ASSERT_EQ(begin+1, set.rend());
+    ASSERT_EQ(end-1, set.rbegin());
+
+    ASSERT_EQ(++begin, set.rend());
+    ASSERT_EQ(--begin, set.rbegin());
+
+    ASSERT_EQ(begin += 1, set.rend());
+    ASSERT_EQ(begin -= 1, set.rbegin());
+
+    ASSERT_EQ(begin + (end - begin), set.rend());
+    ASSERT_EQ(begin - (begin - end), set.rend());
+
+    ASSERT_EQ(end - (end - begin), set.rbegin());
+    ASSERT_EQ(end + (begin - end), set.rbegin());
+
+    ASSERT_EQ(begin[0], *set.rbegin());
+
+    ASSERT_LT(begin, end);
+    ASSERT_LE(begin, set.rbegin());
+
+    ASSERT_GT(end, begin);
+    ASSERT_GE(end, set.rend());
+
+    ASSERT_EQ(*begin, entt::entity{3});
+}
+
 TEST(SparseSet, Find) {
     entt::sparse_set<entt::entity> set;
     set.emplace(entt::entity{3});