diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-26 18:04:12 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-03-27 07:02:35 +0100 |
| commit | 4b094e2bd5a8e60ec1018d6aa90aa9da4adf49c9 (patch) | |
| tree | f96ab182776f58d46a3cf47882855995de109a64 /libs | |
| parent | aa68f53d2502e0ea81c8e9c95e37d9847cb6cb16 (diff) | |
| download | teachos-4b094e2bd5a8e60ec1018d6aa90aa9da4adf49c9.tar.xz teachos-4b094e2bd5a8e60ec1018d6aa90aa9da4adf49c9.zip | |
kstd/vector: implement single-element erase
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/kstd/include/kstd/vector | 16 | ||||
| -rw-r--r-- | libs/kstd/tests/src/vector.cpp | 91 |
2 files changed, 107 insertions, 0 deletions
diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector index 0d4aac8..74aefa9 100644 --- a/libs/kstd/include/kstd/vector +++ b/libs/kstd/include/kstd/vector @@ -690,6 +690,22 @@ namespace kstd return begin() + prefix_size; } + constexpr auto erase(const_iterator position) -> iterator + { + if (position == end()) + { + os::panic("[kstd:vector] Attempted to erase end()!"); + } + + auto prefix_size = std::ranges::distance(cbegin(), position); + + std::ranges::move(begin() + prefix_size + 1, end(), begin() + prefix_size); + std::allocator_traits<allocator_type>::destroy(m_allocator, end() - 1); + --m_size; + + return begin() + prefix_size; + } + //! Append a given element to this vector via copy construction. constexpr auto push_back(value_type const & value) -> void { diff --git a/libs/kstd/tests/src/vector.cpp b/libs/kstd/tests/src/vector.cpp index 0735c9a..3ff041f 100644 --- a/libs/kstd/tests/src/vector.cpp +++ b/libs/kstd/tests/src/vector.cpp @@ -649,6 +649,45 @@ SCENARIO("Vector modifiers", "[vector]") REQUIRE(it == v.begin() + 1); } } + + WHEN("erasing the first element") + { + auto it = v.erase(v.cbegin()); + + THEN("the first element is removed and the size decreases") + { + REQUIRE(v.size() == 2); + REQUIRE(v[0] == 20); + REQUIRE(v[1] == 30); + REQUIRE(it == v.begin()); + } + } + + WHEN("erasing a middle element") + { + auto it = v.erase(v.cbegin() + 1); + + THEN("the middle element is removed and the size decreases") + { + REQUIRE(v.size() == 2); + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 30); + REQUIRE(it == v.begin() + 1); + } + } + + WHEN("erasing the last element") + { + auto it = v.erase(v.cend() - 1); + + THEN("the last element is removed and the size decreases") + { + REQUIRE(v.size() == 2); + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 20); + REQUIRE(it == v.end()); + } + } } } @@ -868,6 +907,58 @@ SCENARIO("Vector modifier move semantics", "[vector]") REQUIRE(v[3].was_moved); } } + + WHEN("erasing an element in the middle") + { + for (auto& elem : v) + { + elem.was_copied = false; + elem.was_moved = false; + } + + auto it = v.erase(v.cbegin() + 1); + + THEN("the subsequent elements are move-assigned leftwards") + { + REQUIRE(v.size() == 2); + + REQUIRE(v[0].value == 10); + REQUIRE_FALSE(v[0].was_moved); + REQUIRE_FALSE(v[0].was_copied); + + REQUIRE(v[1].value == 30); + REQUIRE(v[1].was_moved); + REQUIRE_FALSE(v[1].was_copied); + + REQUIRE(it == v.begin() + 1); + } + } + + WHEN("erasing the last element") + { + for (auto& elem : v) + { + elem.was_copied = false; + elem.was_moved = false; + } + + auto it = v.erase(v.cend() - 1); + + THEN("no elements are moved, just the last element destroyed") + { + REQUIRE(v.size() == 2); + + REQUIRE(v[0].value == 10); + REQUIRE_FALSE(v[0].was_moved); + REQUIRE_FALSE(v[0].was_copied); + + REQUIRE(v[1].value == 20); + REQUIRE_FALSE(v[1].was_moved); + REQUIRE_FALSE(v[1].was_copied); + + REQUIRE(it == v.end()); + } + } } } |
