diff options
| -rw-r--r-- | libs/kstd/kstd/vector.hpp | 34 | ||||
| -rw-r--r-- | libs/kstd/kstd/vector.tests.cpp | 85 |
2 files changed, 119 insertions, 0 deletions
diff --git a/libs/kstd/kstd/vector.hpp b/libs/kstd/kstd/vector.hpp index d6ad232a..71c380fc 100644 --- a/libs/kstd/kstd/vector.hpp +++ b/libs/kstd/kstd/vector.hpp @@ -1078,6 +1078,40 @@ namespace kstd template<std::ranges::input_range Range, typename Allocator = kstd::allocator<std::ranges::range_value_t<Range>>> vector(kstd::from_range_t, Range &&, Allocator = Allocator()) -> vector<std::ranges::range_value_t<Range>, Allocator>; + //! Erase all occurrences of a given element from a vector. + //! + //! @tparam ValueType The value type of the vector. + //! @tparam Allocator The allocator type used by the vector. + //! @tparam NeedleType The type of the element to erase. + //! @param haystack The vector to erase all occurrences of the element from. + //! @param needle The element to erase from the vector. + //! @return The number of erased elements. + template<typename ValueType, typename Allocator, typename NeedleType = ValueType> + constexpr auto erase(vector<ValueType, Allocator> & haystack, NeedleType const & needle) + -> std::remove_cvref_t<decltype(haystack)>::size_type + { + auto removed = std::ranges::remove(haystack, needle); + haystack.erase(removed.begin(), removed.end()); + return std::ranges::distance(removed); + } + + //! Erase all element fulfilling a given predicate from the vector. + //! + //! @tparam ValueType The value type of the vector. + //! @tparam Allocator The allocator type used by the vector. + //! @tparam Predicate The type of the predicate to check for the elements. + //! @param haystack The vector to erase all occurrences of the element from. + //! @param predicate The predicate to check for the element. + //! @return The number of erased elements. + template<typename ValueType, typename Allocator, typename Predicate> + constexpr auto erase_if(vector<ValueType, Allocator> & haystack, Predicate predicate) + -> std::remove_cvref_t<decltype(haystack)>::size_type + { + auto removed = std::ranges::remove_if(haystack, predicate); + haystack.erase(removed.begin(), removed.end()); + return std::ranges::distance(removed); + } + } // namespace kstd #endif diff --git a/libs/kstd/kstd/vector.tests.cpp b/libs/kstd/kstd/vector.tests.cpp index 72c1127a..24598bf9 100644 --- a/libs/kstd/kstd/vector.tests.cpp +++ b/libs/kstd/kstd/vector.tests.cpp @@ -1043,6 +1043,91 @@ SCENARIO("Vector modifiers", "[vector]") } } + WHEN("erasing an element using free erase") + { + auto erased = kstd::erase(v, 20); + + THEN("the number of erased elements is 1") + { + REQUIRE(erased == 1); + } + + THEN("the size is reduced") + { + REQUIRE(v.size() == 2); + } + + THEN("the element is erased") + { + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 30); + } + } + + WHEN("erasing a non-existing element using free erase") + { + auto erased = kstd::erase(v, 40); + + THEN("the number of erased elements is 0") + { + REQUIRE(erased == 0); + } + + THEN("the size stays the same") + { + REQUIRE(v.size() == 3); + } + + THEN("no element is erased") + { + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 20); + REQUIRE(v[2] == 30); + } + } + + WHEN("erasing a elements using free erase_if") + { + auto erased = kstd::erase_if(v, [](auto x) { return x >= 20; }); + + THEN("the number of erased elements is 2") + { + REQUIRE(erased == 2); + } + + THEN("the size is reduced") + { + REQUIRE(v.size() == 1); + } + + THEN("the elements are erased") + { + REQUIRE(v[0] == 10); + } + } + + WHEN("erasing non-existing elements using free erase_if") + { + auto erased = kstd::erase_if(v, [](auto x) { return x >= 40; }); + + THEN("the number of erased elements is 0") + { + REQUIRE(erased == 0); + } + + THEN("the size stays the same") + { + REQUIRE(v.size() == 3); + } + + THEN("no element is erased") + { + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 20); + REQUIRE(v[2] == 30); + } + } + WHEN("appending a range") { auto initial_size = v.size(); |
