Michele Caini 3 лет назад
Родитель
Сommit
fccdff05e3
2 измененных файлов с 93 добавлено и 11 удалено
  1. 41 1
      src/entt/container/dense_map.hpp
  2. 52 10
      test/entt/container/dense_map.cpp

+ 41 - 1
src/entt/container/dense_map.hpp

@@ -786,7 +786,7 @@ public:
 
     /**
      * @brief Finds an element with a key that compares _equivalent_ to a given
-     * value.
+     * key.
      * @tparam Other Type of the key value of an element to search for.
      * @param key Key value of an element to search for.
      * @return An iterator to an element with the given key. If no such element
@@ -805,6 +805,46 @@ public:
         return constrained_find(key, key_to_bucket(key));
     }
 
+    /**
+     * @brief Returns a range containing all elements with a given key.
+     * @param key Key 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 key_type &key) {
+        const auto it = find(key);
+        return {it, it + !(it == end())};
+    }
+
+    /*! @copydoc equal_range */
+    [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const {
+        const auto it = find(key);
+        return {it, it + !(it == cend())};
+    }
+
+    /**
+     * @brief Returns a range containing all elements that compare _equivalent_
+     * to a given key.
+     * @tparam Other Type of an element to search for.
+     * @param key Key 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 &key) {
+        const auto it = find(key);
+        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 &key) const {
+        const auto it = find(key);
+        return {it, it + !(it == cend())};
+    }
+
     /**
      * @brief Checks if the container contains an element with a given key.
      * @param key Key value of an element to search for.

+ 52 - 10
test/entt/container/dense_map.cpp

@@ -28,6 +28,7 @@ struct transparent_equal_to {
 
 TEST(DenseMap, Functionalities) {
     entt::dense_map<int, int, entt::identity, transparent_equal_to> map;
+    const auto &cmap = map;
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = map.get_allocator());
 
@@ -42,7 +43,7 @@ TEST(DenseMap, Functionalities) {
     ASSERT_EQ(map.max_load_factor(), .9f);
 
     ASSERT_EQ(map.begin(), map.end());
-    ASSERT_EQ(std::as_const(map).begin(), std::as_const(map).end());
+    ASSERT_EQ(cmap.begin(), cmap.end());
     ASSERT_EQ(map.cbegin(), map.cend());
 
     ASSERT_NE(map.max_bucket_count(), 0u);
@@ -55,7 +56,7 @@ TEST(DenseMap, Functionalities) {
     ASSERT_EQ(map.bucket(10), 2u);
 
     ASSERT_EQ(map.begin(1u), map.end(1u));
-    ASSERT_EQ(std::as_const(map).begin(1u), std::as_const(map).end(1u));
+    ASSERT_EQ(cmap.begin(1u), cmap.end(1u));
     ASSERT_EQ(map.cbegin(1u), map.cend(1u));
 
     ASSERT_FALSE(map.contains(42));
@@ -63,8 +64,8 @@ TEST(DenseMap, Functionalities) {
 
     ASSERT_EQ(map.find(42), map.end());
     ASSERT_EQ(map.find(4.2), map.end());
-    ASSERT_EQ(std::as_const(map).find(42), map.cend());
-    ASSERT_EQ(std::as_const(map).find(4.2), map.cend());
+    ASSERT_EQ(cmap.find(42), map.cend());
+    ASSERT_EQ(cmap.find(4.2), map.cend());
 
     ASSERT_EQ(map.hash_function()(42), 42);
     ASSERT_TRUE(map.key_eq()(42, 42));
@@ -73,14 +74,14 @@ TEST(DenseMap, Functionalities) {
 
     ASSERT_EQ(map.count(0), 1u);
     ASSERT_EQ(map.count(4.2), 0u);
-    ASSERT_EQ(std::as_const(map).count(0.0), 1u);
-    ASSERT_EQ(std::as_const(map).count(42), 0u);
+    ASSERT_EQ(cmap.count(0.0), 1u);
+    ASSERT_EQ(cmap.count(42), 0u);
 
     ASSERT_FALSE(map.empty());
     ASSERT_EQ(map.size(), 1u);
 
     ASSERT_NE(map.begin(), map.end());
-    ASSERT_NE(std::as_const(map).begin(), std::as_const(map).end());
+    ASSERT_NE(cmap.begin(), cmap.end());
     ASSERT_NE(map.cbegin(), map.cend());
 
     ASSERT_TRUE(map.contains(0));
@@ -92,7 +93,7 @@ TEST(DenseMap, Functionalities) {
     ASSERT_EQ(map.size(), 0u);
 
     ASSERT_EQ(map.begin(), map.end());
-    ASSERT_EQ(std::as_const(map).begin(), std::as_const(map).end());
+    ASSERT_EQ(cmap.begin(), cmap.end());
     ASSERT_EQ(map.cbegin(), map.cend());
 
     ASSERT_FALSE(map.contains(0));
@@ -925,8 +926,48 @@ TEST(DenseMap, Swap) {
     ASSERT_TRUE(other.contains(0));
 }
 
+TEST(DenseMap, EqualRange) {
+    entt::dense_map<int, int, entt::identity, transparent_equal_to> map;
+    const auto &cmap = map;
+
+    map.emplace(42, 3);
+
+    ASSERT_EQ(map.equal_range(0).first, map.end());
+    ASSERT_EQ(map.equal_range(0).second, map.end());
+
+    ASSERT_EQ(cmap.equal_range(0).first, cmap.cend());
+    ASSERT_EQ(cmap.equal_range(0).second, cmap.cend());
+
+    ASSERT_EQ(map.equal_range(0.0).first, map.end());
+    ASSERT_EQ(map.equal_range(0.0).second, map.end());
+
+    ASSERT_EQ(cmap.equal_range(0.0).first, cmap.cend());
+    ASSERT_EQ(cmap.equal_range(0.0).second, cmap.cend());
+
+    ASSERT_NE(map.equal_range(42).first, map.end());
+    ASSERT_EQ(map.equal_range(42).first->first, 42);
+    ASSERT_EQ(map.equal_range(42).first->second, 3);
+    ASSERT_EQ(map.equal_range(42).second, map.end());
+
+    ASSERT_NE(cmap.equal_range(42).first, cmap.cend());
+    ASSERT_EQ(cmap.equal_range(42).first->first, 42);
+    ASSERT_EQ(cmap.equal_range(42).first->second, 3);
+    ASSERT_EQ(cmap.equal_range(42).second, cmap.cend());
+
+    ASSERT_NE(map.equal_range(42.0).first, map.end());
+    ASSERT_EQ(map.equal_range(42.0).first->first, 42);
+    ASSERT_EQ(map.equal_range(42.0).first->second, 3);
+    ASSERT_EQ(map.equal_range(42.0).second, map.end());
+
+    ASSERT_NE(cmap.equal_range(42.0).first, cmap.cend());
+    ASSERT_EQ(cmap.equal_range(42.0).first->first, 42);
+    ASSERT_EQ(cmap.equal_range(42.0).first->second, 3);
+    ASSERT_EQ(cmap.equal_range(42.0).second, cmap.cend());
+}
+
 TEST(DenseMap, Indexing) {
     entt::dense_map<int, int> map;
+    const auto &cmap = map;
     const auto key = 1;
 
     ASSERT_FALSE(map.contains(key));
@@ -935,14 +976,15 @@ TEST(DenseMap, Indexing) {
 
     ASSERT_TRUE(map.contains(key));
     ASSERT_EQ(map[std::move(key)], 99);
-    ASSERT_EQ(std::as_const(map).at(key), 99);
+    ASSERT_EQ(cmap.at(key), 99);
     ASSERT_EQ(map.at(key), 99);
 }
 
 ENTT_DEBUG_TEST(DenseMapDeathTest, Indexing) {
     entt::dense_map<int, int> map;
+    const auto &cmap = map;
 
-    ASSERT_DEATH([[maybe_unused]] auto value = std::as_const(map).at(0), "");
+    ASSERT_DEATH([[maybe_unused]] auto value = cmap.at(0), "");
     ASSERT_DEATH([[maybe_unused]] auto value = map.at(42), "");
 }