Răsfoiți Sursa

group: rbegin/rend

Michele Caini 5 ani în urmă
părinte
comite
b205a5e49d
2 a modificat fișierele cu 96 adăugiri și 12 ștergeri
  1. 78 4
      src/entt/entity/group.hpp
  2. 18 8
      test/entt/entity/group.cpp

+ 78 - 4
src/entt/entity/group.hpp

@@ -180,6 +180,8 @@ public:
     using size_type = std::size_t;
     /*! @brief Random access iterator type. */
     using iterator = typename sparse_set<Entity>::iterator;
+    /*! @brief Reversed iterator type. */
+    using reverse_iterator = typename sparse_set<Entity>::reverse_iterator;
 
     /**
      * @brief Returns the number of existing components of the given type.
@@ -315,6 +317,41 @@ public:
         return handler->end();
     }
 
+    /**
+     * @brief Returns an iterator to the first entity of the reversed group.
+     *
+     * The returned iterator points to the first entity of the reversed group.
+     * If the group is empty, the returned iterator will be equal to `rend()`.
+     *
+     * @note
+     * Iterators stay true to the order imposed to the underlying data
+     * structures.
+     *
+     * @return An iterator to the first entity of the reversed group.
+     */
+    [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
+        return handler->rbegin();
+    }
+
+    /**
+     * @brief Returns an iterator that is past the last entity of the reversed
+     * group.
+     *
+     * The returned iterator points to the entity following the last entity of
+     * the reversed group. Attempting to dereference the returned iterator
+     * results in undefined behavior.
+     *
+     * @note
+     * Iterators stay true to the order imposed to the underlying data
+     * structures.
+     *
+     * @return An iterator to the entity following the last entity of the
+     * reversed group.
+     */
+    [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
+        return handler->rend();
+    }
+
     /**
      * @brief Returns the first entity of the group, if any.
      * @return The first entity of the group if one exists, the null entity
@@ -331,8 +368,8 @@ public:
      * otherwise.
      */
     [[nodiscard]] entity_type back() const {
-        const auto it = std::make_reverse_iterator(end());
-        return it != std::make_reverse_iterator(begin()) ? *it : null;
+        const auto it = rbegin();
+        return it != rend() ? *it : null;
     }
 
     /**
@@ -720,6 +757,8 @@ public:
     using size_type = std::size_t;
     /*! @brief Random access iterator type. */
     using iterator = typename sparse_set<Entity>::iterator;
+    /*! @brief Reversed iterator type. */
+    using reverse_iterator = typename sparse_set<Entity>::reverse_iterator;
 
     /**
      * @brief Returns the number of existing components of the given type.
@@ -847,6 +886,41 @@ public:
         return std::get<0>(pools)->sparse_set<entity_type>::end();
     }
 
+    /**
+     * @brief Returns an iterator to the first entity of the reversed group.
+     *
+     * The returned iterator points to the first entity of the reversed group.
+     * If the group is empty, the returned iterator will be equal to `rend()`.
+     *
+     * @note
+     * Iterators stay true to the order imposed to the underlying data
+     * structures.
+     *
+     * @return An iterator to the first entity of the reversed group.
+     */
+    [[nodiscard]] reverse_iterator rbegin() const ENTT_NOEXCEPT {
+        return std::get<0>(pools)->sparse_set<entity_type>::rbegin();
+    }
+
+    /**
+     * @brief Returns an iterator that is past the last entity of the reversed
+     * group.
+     *
+     * The returned iterator points to the entity following the last entity of
+     * the reversed group. Attempting to dereference the returned iterator
+     * results in undefined behavior.
+     *
+     * @note
+     * Iterators stay true to the order imposed to the underlying data
+     * structures.
+     *
+     * @return An iterator to the entity following the last entity of the
+     * reversed group.
+     */
+    [[nodiscard]] reverse_iterator rend() const ENTT_NOEXCEPT {
+        return std::get<0>(pools)->sparse_set<entity_type>::rbegin() + *length;
+    }
+
     /**
      * @brief Returns the first entity of the group, if any.
      * @return The first entity of the group if one exists, the null entity
@@ -863,8 +937,8 @@ public:
      * otherwise.
      */
     [[nodiscard]] entity_type back() const {
-        const auto it = std::make_reverse_iterator(end());
-        return it != std::make_reverse_iterator(begin()) ? *it : null;
+        const auto it = rbegin();
+        return it != rend() ? *it : null;
     }
 
     /**

+ 18 - 8
test/entt/entity/group.cpp

@@ -30,13 +30,16 @@ TEST(NonOwningGroup, Functionalities) {
     registry.emplace<char>(e1);
 
     ASSERT_FALSE(group.empty());
-    ASSERT_FALSE((group.empty<int>()));
-    ASSERT_FALSE((cgroup.empty<const char>()));
-    ASSERT_NO_THROW((group.begin()++));
-    ASSERT_NO_THROW((++cgroup.begin()));
+    ASSERT_FALSE(group.empty<int>());
+    ASSERT_FALSE(cgroup.empty<const char>());
+    ASSERT_NO_THROW(group.begin()++);
+    ASSERT_NO_THROW(++cgroup.begin());
+    ASSERT_EQ(group.rbegin(), cgroup.rbegin());
 
     ASSERT_NE(group.begin(), group.end());
     ASSERT_NE(cgroup.begin(), cgroup.end());
+    ASSERT_NE(group.rbegin(), group.rend());
+    ASSERT_NE(cgroup.rbegin(), cgroup.rend());
     ASSERT_EQ(group.size(), typename decltype(group)::size_type{1});
     ASSERT_EQ(group.size<int>(), typename decltype(group)::size_type{1});
     ASSERT_EQ(cgroup.size<const char>(), typename decltype(group)::size_type{2});
@@ -78,6 +81,8 @@ TEST(NonOwningGroup, Functionalities) {
 
     ASSERT_EQ(group.begin(), group.end());
     ASSERT_EQ(cgroup.begin(), cgroup.end());
+    ASSERT_EQ(group.rbegin(), group.rend());
+    ASSERT_EQ(cgroup.rbegin(), cgroup.rend());
     ASSERT_TRUE(group.empty());
 
     ASSERT_TRUE(group.capacity());
@@ -590,13 +595,16 @@ TEST(OwningGroup, Functionalities) {
     registry.emplace<char>(e1);
 
     ASSERT_FALSE(group.empty());
-    ASSERT_FALSE((group.empty<int>()));
-    ASSERT_FALSE((cgroup.empty<const char>()));
-    ASSERT_NO_THROW((group.begin()++));
-    ASSERT_NO_THROW((++cgroup.begin()));
+    ASSERT_FALSE(group.empty<int>());
+    ASSERT_FALSE(cgroup.empty<const char>());
+    ASSERT_NO_THROW(group.begin()++);
+    ASSERT_NO_THROW(++cgroup.begin());
+    ASSERT_EQ(group.rbegin(), cgroup.rbegin());
 
     ASSERT_NE(group.begin(), group.end());
     ASSERT_NE(cgroup.begin(), cgroup.end());
+    ASSERT_NE(group.rbegin(), group.rend());
+    ASSERT_NE(cgroup.rbegin(), cgroup.rend());
     ASSERT_EQ(group.size(), typename decltype(group)::size_type{1});
     ASSERT_EQ(group.size<int>(), typename decltype(group)::size_type{1});
     ASSERT_EQ(cgroup.size<const char>(), typename decltype(group)::size_type{2});
@@ -641,6 +649,8 @@ TEST(OwningGroup, Functionalities) {
 
     ASSERT_EQ(group.begin(), group.end());
     ASSERT_EQ(cgroup.begin(), cgroup.end());
+    ASSERT_EQ(group.rbegin(), group.rend());
+    ASSERT_EQ(cgroup.rbegin(), cgroup.rend());
     ASSERT_TRUE(group.empty());
 }