diff --git a/src/entt/container/dense_map.hpp b/src/entt/container/dense_map.hpp index 6d29c56cc..163869bc9 100644 --- a/src/entt/container/dense_map.hpp +++ b/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 equal_range(const key_type &key) { + const auto it = find(key); + return {it, it + !(it == end())}; + } + + /*! @copydoc equal_range */ + [[nodiscard]] std::pair 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 + [[nodiscard]] std::enable_if_t && is_transparent_v, std::conditional_t>> + equal_range(const Other &key) { + const auto it = find(key); + return {it, it + !(it == end())}; + } + + /*! @copydoc equal_range */ + template + [[nodiscard]] std::enable_if_t && is_transparent_v, std::conditional_t>> + 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. diff --git a/test/entt/container/dense_map.cpp b/test/entt/container/dense_map.cpp index 339a59832..844173a26 100644 --- a/test/entt/container/dense_map.cpp +++ b/test/entt/container/dense_map.cpp @@ -28,6 +28,7 @@ struct transparent_equal_to { TEST(DenseMap, Functionalities) { entt::dense_map 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 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 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 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), ""); }