Parcourir la source

dense_set: equal_range

Michele Caini il y a 3 ans
Parent
commit
e530b3d6f6
2 fichiers modifiés avec 86 ajouts et 10 suppressions
  1. 42 2
      src/entt/container/dense_set.hpp
  2. 44 8
      test/entt/container/dense_set.cpp

+ 42 - 2
src/entt/container/dense_set.hpp

@@ -603,11 +603,11 @@ public:
     }
 
     /**
-     * @brief Returns the number of elements matching a key (either 1 or 0).
+     * @brief Returns the number of elements matching a value (either 1 or 0).
      * @param key Key value of an element to search for.
      * @return Number of elements matching the key (either 1 or 0).
      */
-    [[nodiscard]] size_type count(const key_type &key) const {
+    [[nodiscard]] size_type count(const value_type &key) const {
         return find(key) != end();
     }
 
@@ -658,6 +658,46 @@ public:
         return constrained_find(value, value_to_bucket(value));
     }
 
+    /**
+     * @brief Returns a range containing all elements with a given value.
+     * @param value Value of an element to search for.
+     * @return A pair of iterators pointing to the first element and past the
+     * last element of the range.
+     */
+    [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) {
+        const auto it = find(value);
+        return {it, it + !(it == end())};
+    }
+
+    /*! @copydoc equal_range */
+    [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const {
+        const auto it = find(value);
+        return {it, it + !(it == cend())};
+    }
+
+    /**
+     * @brief Returns a range containing all elements that compare _equivalent_
+     * to a given value.
+     * @tparam Other Type of an element to search for.
+     * @param value Value of an element to search for.
+     * @return A pair of iterators pointing to the first element and past the
+     * last element of the range.
+     */
+    template<typename Other>
+    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>>
+    equal_range(const Other &value) {
+        const auto it = find(value);
+        return {it, it + !(it == end())};
+    }
+
+    /*! @copydoc equal_range */
+    template<class Other>
+    [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>>
+    equal_range(const Other &value) const {
+        const auto it = find(value);
+        return {it, it + !(it == cend())};
+    }
+
     /**
      * @brief Checks if the container contains an element with a given value.
      * @param value Value of an element to search for.

+ 44 - 8
test/entt/container/dense_set.cpp

@@ -26,6 +26,7 @@ struct transparent_equal_to {
 
 TEST(DenseSet, Functionalities) {
     entt::dense_set<int, entt::identity, transparent_equal_to> set;
+    const auto &cset = set;
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
 
@@ -40,7 +41,7 @@ TEST(DenseSet, Functionalities) {
     ASSERT_EQ(set.max_load_factor(), .9f);
 
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.cbegin(), set.cend());
 
     ASSERT_NE(set.max_bucket_count(), 0u);
@@ -53,7 +54,7 @@ TEST(DenseSet, Functionalities) {
     ASSERT_EQ(set.bucket(10), 2u);
 
     ASSERT_EQ(set.begin(1u), set.end(1u));
-    ASSERT_EQ(std::as_const(set).begin(1u), std::as_const(set).end(1u));
+    ASSERT_EQ(cset.begin(1u), cset.end(1u));
     ASSERT_EQ(set.cbegin(1u), set.cend(1u));
 
     ASSERT_FALSE(set.contains(42));
@@ -61,8 +62,8 @@ TEST(DenseSet, Functionalities) {
 
     ASSERT_EQ(set.find(42), set.end());
     ASSERT_EQ(set.find(4.2), set.end());
-    ASSERT_EQ(std::as_const(set).find(42), set.cend());
-    ASSERT_EQ(std::as_const(set).find(4.2), set.cend());
+    ASSERT_EQ(cset.find(42), set.cend());
+    ASSERT_EQ(cset.find(4.2), set.cend());
 
     ASSERT_EQ(set.hash_function()(42), 42);
     ASSERT_TRUE(set.key_eq()(42, 42));
@@ -71,14 +72,14 @@ TEST(DenseSet, Functionalities) {
 
     ASSERT_EQ(set.count(0), 1u);
     ASSERT_EQ(set.count(4.2), 0u);
-    ASSERT_EQ(std::as_const(set).count(0.0), 1u);
-    ASSERT_EQ(std::as_const(set).count(42), 0u);
+    ASSERT_EQ(cset.count(0.0), 1u);
+    ASSERT_EQ(cset.count(42), 0u);
 
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 1u);
 
     ASSERT_NE(set.begin(), set.end());
-    ASSERT_NE(std::as_const(set).begin(), std::as_const(set).end());
+    ASSERT_NE(cset.begin(), cset.end());
     ASSERT_NE(set.cbegin(), set.cend());
 
     ASSERT_TRUE(set.contains(0));
@@ -90,7 +91,7 @@ TEST(DenseSet, Functionalities) {
     ASSERT_EQ(set.size(), 0u);
 
     ASSERT_EQ(set.begin(), set.end());
-    ASSERT_EQ(std::as_const(set).begin(), std::as_const(set).end());
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.cbegin(), set.cend());
 
     ASSERT_FALSE(set.contains(0));
@@ -678,6 +679,41 @@ TEST(DenseSet, Swap) {
     ASSERT_TRUE(other.contains(0));
 }
 
+TEST(DenseSet, EqualRange) {
+    entt::dense_set<int, entt::identity, transparent_equal_to> set;
+    const auto &cset = set;
+
+    set.emplace(42);
+
+    ASSERT_EQ(set.equal_range(0).first, set.end());
+    ASSERT_EQ(set.equal_range(0).second, set.end());
+
+    ASSERT_EQ(cset.equal_range(0).first, cset.cend());
+    ASSERT_EQ(cset.equal_range(0).second, cset.cend());
+
+    ASSERT_EQ(set.equal_range(0.0).first, set.end());
+    ASSERT_EQ(set.equal_range(0.0).second, set.end());
+
+    ASSERT_EQ(cset.equal_range(0.0).first, cset.cend());
+    ASSERT_EQ(cset.equal_range(0.0).second, cset.cend());
+
+    ASSERT_NE(set.equal_range(42).first, set.end());
+    ASSERT_EQ(*set.equal_range(42).first, 42);
+    ASSERT_EQ(set.equal_range(42).second, set.end());
+
+    ASSERT_NE(cset.equal_range(42).first, cset.cend());
+    ASSERT_EQ(*cset.equal_range(42).first, 42);
+    ASSERT_EQ(cset.equal_range(42).second, cset.cend());
+
+    ASSERT_NE(set.equal_range(42.0).first, set.end());
+    ASSERT_EQ(*set.equal_range(42.0).first, 42);
+    ASSERT_EQ(set.equal_range(42.0).second, set.end());
+
+    ASSERT_NE(cset.equal_range(42.0).first, cset.cend());
+    ASSERT_EQ(*cset.equal_range(42.0).first, 42);
+    ASSERT_EQ(cset.equal_range(42.0).second, cset.cend());
+}
+
 TEST(DenseSet, LocalIterator) {
     using iterator = typename entt::dense_set<std::size_t, entt::identity>::local_iterator;