Sfoglia il codice sorgente

dense_set: reverse iterators

Michele Caini 2 anni fa
parent
commit
4b1a19677a
2 ha cambiato i file con 150 aggiunte e 0 eliminazioni
  1. 44 0
      src/entt/container/dense_set.hpp
  2. 106 0
      test/entt/container/dense_set.cpp

+ 44 - 0
src/entt/container/dense_set.hpp

@@ -311,6 +311,10 @@ public:
     using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>;
     /*! @brief Constant random access iterator type. */
     using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>;
+    /*! @brief Reverse iterator type. */
+    using reverse_iterator = std::reverse_iterator<iterator>;
+    /*! @brief Constant reverse iterator type. */
+    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
     /*! @brief Forward iterator type. */
     using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>;
     /*! @brief Constant forward iterator type. */
@@ -447,6 +451,46 @@ public:
         return packed.first().end();
     }
 
+    /**
+     * @brief Returns a reverse iterator to the beginning.
+     *
+     * If the array 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 noexcept {
+        return std::make_reverse_iterator(cend());
+    }
+
+    /*! @copydoc crbegin */
+    [[nodiscard]] const_reverse_iterator rbegin() const noexcept {
+        return crbegin();
+    }
+
+    /*! @copydoc rbegin */
+    [[nodiscard]] reverse_iterator rbegin() noexcept {
+        return std::make_reverse_iterator(end());
+    }
+
+    /**
+     * @brief Returns a reverse iterator to the end.
+     * @return An iterator to the element following the last instance of the
+     * reversed internal array.
+     */
+    [[nodiscard]] const_reverse_iterator crend() const noexcept {
+        return std::make_reverse_iterator(cbegin());
+    }
+
+    /*! @copydoc crend */
+    [[nodiscard]] const_reverse_iterator rend() const noexcept {
+        return crend();
+    }
+
+    /*! @copydoc rend */
+    [[nodiscard]] reverse_iterator rend() noexcept {
+        return std::make_reverse_iterator(begin());
+    }
+
     /**
      * @brief Checks whether a container is empty.
      * @return True if the container is empty, false otherwise.

+ 106 - 0
test/entt/container/dense_set.cpp

@@ -280,6 +280,112 @@ TEST(DenseSet, ConstIterator) {
     ASSERT_EQ(cbegin[1u], 42);
 }
 
+TEST(DenseSet, ReverseIterator) {
+    using iterator = typename entt::dense_set<int>::reverse_iterator;
+
+    static_assert(std::is_same_v<iterator::value_type, int>);
+    static_assert(std::is_same_v<iterator::pointer, const int *>);
+    static_assert(std::is_same_v<iterator::reference, const int &>);
+
+    entt::dense_set<int> set;
+    set.emplace(3);
+
+    iterator end{set.rbegin()};
+    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[0u], *set.rbegin().operator->());
+    ASSERT_EQ(begin[0u], *set.rbegin());
+
+    ASSERT_LT(begin, end);
+    ASSERT_LE(begin, set.rbegin());
+
+    ASSERT_GT(end, begin);
+    ASSERT_GE(end, set.rend());
+
+    set.emplace(42);
+    begin = set.rbegin();
+
+    ASSERT_EQ(begin[0u], 42);
+    ASSERT_EQ(begin[1u], 3);
+}
+
+TEST(DenseSet, ConstReverseIterator) {
+    using iterator = typename entt::dense_set<int>::const_reverse_iterator;
+
+    static_assert(std::is_same_v<iterator::value_type, int>);
+    static_assert(std::is_same_v<iterator::pointer, const int *>);
+    static_assert(std::is_same_v<iterator::reference, const int &>);
+
+    entt::dense_set<int> set;
+    set.emplace(3);
+
+    iterator cend{set.crbegin()};
+    iterator cbegin{};
+    cbegin = set.crend();
+    std::swap(cbegin, cend);
+
+    ASSERT_EQ(cbegin, set.crbegin());
+    ASSERT_EQ(cend, set.crend());
+    ASSERT_NE(cbegin, cend);
+
+    ASSERT_EQ(cbegin++, set.crbegin());
+    ASSERT_EQ(cbegin--, set.crend());
+
+    ASSERT_EQ(cbegin + 1, set.crend());
+    ASSERT_EQ(cend - 1, set.crbegin());
+
+    ASSERT_EQ(++cbegin, set.crend());
+    ASSERT_EQ(--cbegin, set.crbegin());
+
+    ASSERT_EQ(cbegin += 1, set.crend());
+    ASSERT_EQ(cbegin -= 1, set.crbegin());
+
+    ASSERT_EQ(cbegin + (cend - cbegin), set.crend());
+    ASSERT_EQ(cbegin - (cbegin - cend), set.crend());
+
+    ASSERT_EQ(cend - (cend - cbegin), set.crbegin());
+    ASSERT_EQ(cend + (cbegin - cend), set.crbegin());
+
+    ASSERT_EQ(cbegin[0u], *set.crbegin().operator->());
+    ASSERT_EQ(cbegin[0u], *set.crbegin());
+
+    ASSERT_LT(cbegin, cend);
+    ASSERT_LE(cbegin, set.crbegin());
+
+    ASSERT_GT(cend, cbegin);
+    ASSERT_GE(cend, set.crend());
+
+    set.emplace(42);
+    cbegin = set.crbegin();
+
+    ASSERT_EQ(cbegin[0u], 42);
+    ASSERT_EQ(cbegin[1u], 3);
+}
+
 TEST(DenseSet, IteratorConversion) {
     entt::dense_set<int> set;
     set.emplace(3);