Explorar el Código

storage: added reverse iterators

Michele Caini hace 5 años
padre
commit
cf903aa082
Se han modificado 2 ficheros con 141 adiciones y 13 borrados
  1. 57 13
      src/entt/entity/storage.hpp
  2. 84 0
      test/entt/entity/storage.cpp

+ 57 - 13
src/entt/entity/storage.hpp

@@ -165,6 +165,11 @@ public:
     using iterator = storage_iterator<false>;
     /*! @brief Constant random access iterator type. */
     using const_iterator = storage_iterator<true>;
+    /*! @brief Reverse iterator type. */
+    using reverse_iterator = Type *;
+    /*! @brief Constant reverse iterator type. */
+    using const_reverse_iterator = const Type *;
+
 
     /**
      * @brief Increases the capacity of a storage.
@@ -209,14 +214,10 @@ public:
     /**
      * @brief Returns an iterator to the beginning.
      *
-     * The returned iterator points to the first instance of the given type. If
-     * the storage is empty, the returned iterator will be equal to `end()`.
-     *
-     * @note
-     * Random access iterators stay true to the order imposed by a call to
-     * either `sort` or `respect`.
+     * The returned iterator points to the first instance of the internal array.
+     * If the storage is empty, the returned iterator will be equal to `end()`.
      *
-     * @return An iterator to the first instance of the given type.
+     * @return An iterator to the first instance of the internal array.
      */
     [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
         const typename traits_type::difference_type pos = underlying_type::size();
@@ -238,15 +239,11 @@ public:
      * @brief Returns an iterator to the end.
      *
      * The returned iterator points to the element following the last instance
-     * of the given type. Attempting to dereference the returned iterator
+     * of the internal 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
-     * either `sort` or `respect`.
-     *
      * @return An iterator to the element following the last instance of the
-     * given type.
+     * internal array.
      */
     [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
         return const_iterator{instances, {}};
@@ -262,6 +259,53 @@ public:
         return iterator{instances, {}};
     }
 
+    /**
+     * @brief Returns a reverse iterator to the beginning.
+     *
+     * The returned iterator points to the first instance of the reversed
+     * internal array. If the storage is empty, the returned iterator will be
+     * equal to `rend()`.
+     *
+     * @return An iterator to the first instance of the reversed internal array.
+     */
+    [[nodiscard]] const_reverse_iterator crbegin() const ENTT_NOEXCEPT {
+        return instances.data();
+    }
+
+    /*! @copydoc crbegin */
+    [[nodiscard]] const_reverse_iterator rbegin() const ENTT_NOEXCEPT {
+        return crbegin();
+    }
+
+    /*! @copydoc rbegin */
+    [[nodiscard]] reverse_iterator rbegin() ENTT_NOEXCEPT {
+        return instances.data();
+    }
+
+    /**
+     * @brief Returns a reverse iterator to the end.
+     *
+     * The returned iterator points to the element following the last instance
+     * of the reversed internal array. Attempting to dereference the returned
+     * iterator results in undefined behavior.
+     *
+     * @return An iterator to the element following the last instance of the
+     * reversed internal array.
+     */
+    [[nodiscard]] const_reverse_iterator crend() const ENTT_NOEXCEPT {
+        return crbegin() + instances.size();
+    }
+
+    /*! @copydoc crend */
+    [[nodiscard]] const_reverse_iterator rend() const ENTT_NOEXCEPT {
+        return crend();
+    }
+
+    /*! @copydoc rend */
+    [[nodiscard]] reverse_iterator rend() ENTT_NOEXCEPT {
+        return rbegin() + instances.size();
+    }
+
     /**
      * @brief Returns the object associated with an entity.
      *

+ 84 - 0
test/entt/entity/storage.cpp

@@ -218,6 +218,90 @@ TEST(Storage, ConstIterator) {
     ASSERT_GE(cend, pool.cend());
 }
 
+TEST(Storage, ReverseIterator) {
+    using reverse_iterator = typename entt::storage<entt::entity, boxed_int>::reverse_iterator;
+
+    entt::storage<entt::entity, boxed_int> pool;
+    pool.emplace(entt::entity{3}, 42);
+
+    reverse_iterator end{pool.rbegin()};
+    reverse_iterator begin{};
+    begin = pool.rend();
+    std::swap(begin, end);
+
+    ASSERT_EQ(begin, pool.rbegin());
+    ASSERT_EQ(end, pool.rend());
+    ASSERT_NE(begin, end);
+
+    ASSERT_EQ(begin++, pool.rbegin());
+    ASSERT_EQ(begin--, pool.rend());
+
+    ASSERT_EQ(begin+1, pool.rend());
+    ASSERT_EQ(end-1, pool.rbegin());
+
+    ASSERT_EQ(++begin, pool.rend());
+    ASSERT_EQ(--begin, pool.rbegin());
+
+    ASSERT_EQ(begin += 1, pool.rend());
+    ASSERT_EQ(begin -= 1, pool.rbegin());
+
+    ASSERT_EQ(begin + (end - begin), pool.rend());
+    ASSERT_EQ(begin - (begin - end), pool.rend());
+
+    ASSERT_EQ(end - (end - begin), pool.rbegin());
+    ASSERT_EQ(end + (begin - end), pool.rbegin());
+
+    ASSERT_EQ(begin[0].value, pool.rbegin()->value);
+
+    ASSERT_LT(begin, end);
+    ASSERT_LE(begin, pool.rbegin());
+
+    ASSERT_GT(end, begin);
+    ASSERT_GE(end, pool.rend());
+}
+
+TEST(Storage, ConstReverseIterator) {
+    using const_reverse_iterator = typename entt::storage<entt::entity, boxed_int>::const_reverse_iterator;
+
+    entt::storage<entt::entity, boxed_int> pool;
+    pool.emplace(entt::entity{3}, 42);
+
+    const_reverse_iterator cend{pool.crbegin()};
+    const_reverse_iterator cbegin{};
+    cbegin = pool.crend();
+    std::swap(cbegin, cend);
+
+    ASSERT_EQ(cbegin, pool.crbegin());
+    ASSERT_EQ(cend, pool.crend());
+    ASSERT_NE(cbegin, cend);
+
+    ASSERT_EQ(cbegin++, pool.crbegin());
+    ASSERT_EQ(cbegin--, pool.crend());
+
+    ASSERT_EQ(cbegin+1, pool.crend());
+    ASSERT_EQ(cend-1, pool.crbegin());
+
+    ASSERT_EQ(++cbegin, pool.crend());
+    ASSERT_EQ(--cbegin, pool.crbegin());
+
+    ASSERT_EQ(cbegin += 1, pool.crend());
+    ASSERT_EQ(cbegin -= 1, pool.crbegin());
+
+    ASSERT_EQ(cbegin + (cend - cbegin), pool.crend());
+    ASSERT_EQ(cbegin - (cbegin - cend), pool.crend());
+
+    ASSERT_EQ(cend - (cend - cbegin), pool.crbegin());
+    ASSERT_EQ(cend + (cbegin - cend), pool.crbegin());
+
+    ASSERT_EQ(cbegin[0].value, pool.crbegin()->value);
+
+    ASSERT_LT(cbegin, cend);
+    ASSERT_LE(cbegin, pool.crbegin());
+
+    ASSERT_GT(cend, cbegin);
+    ASSERT_GE(cend, pool.crend());
+}
+
 TEST(Storage, Raw) {
     entt::storage<entt::entity, int> pool;