aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-19 13:54:37 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-19 13:54:37 +0100
commitb038db886fd1e2179f543217f5d3ed7b8d964c4a (patch)
tree82d6ab45d5e3770d9b724f36558c2f6a64a789e0 /libs
parent584304d99b6bb43cef8aab9c6bfe22d24a5bf5a0 (diff)
downloadteachos-b038db886fd1e2179f543217f5d3ed7b8d964c4a.tar.xz
teachos-b038db886fd1e2179f543217f5d3ed7b8d964c4a.zip
kstd: fix vector bugs
Diffstat (limited to 'libs')
-rw-r--r--libs/kstd/include/kstd/vector53
1 files changed, 35 insertions, 18 deletions
diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector
index 9709c2a..75f699b 100644
--- a/libs/kstd/include/kstd/vector
+++ b/libs/kstd/include/kstd/vector
@@ -95,8 +95,8 @@ namespace kstd
//! @tparam InputIterator An iterator type used to describe the source range.
//! @param first The start of the source range.
//! @param last The end of the source range.
- template<std::input_iterator InputIterator>
- constexpr vector(InputIterator first, InputIterator last,
+ template<std::forward_iterator ForwardIterator>
+ constexpr vector(ForwardIterator first, ForwardIterator last,
allocator_type const & allocator =
allocator_type{}) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>)
: m_allocator{allocator}
@@ -114,7 +114,8 @@ namespace kstd
//!
//!
template<typename Range>
- requires(std::ranges::input_range<Range> && std::convertible_to<std::ranges::range_reference_t<Range>, T>)
+ requires(std::ranges::input_range<Range> && std::ranges::sized_range<Range> &&
+ std::convertible_to<std::ranges::range_reference_t<Range>, T>)
constexpr vector(kstd::from_range_t, Range && range, allocator_type const & allocator = allocator_type{})
: m_allocator{allocator}
, m_size{std::ranges::size(range)}
@@ -170,10 +171,26 @@ namespace kstd
//! @param allocator The allocator to use in the vector.
constexpr vector(vector && other, std::type_identity_t<Allocator> const & allocator)
: m_allocator{allocator}
- , m_size{std::exchange(other.m_size, size_type{})}
- , m_capacity(std::exchange(other.m_capacity, size_type{}))
- , m_data(std::exchange(other.m_data, nullptr))
- {}
+ , m_size{}
+ , m_capacity{}
+ , m_data{}
+ {
+ if constexpr (!std::allocator_traits<allocator_type>::is_always_equal::value)
+ {
+ if (m_allocator != other.m_allocator)
+ {
+ m_capacity = other.size();
+ m_data = allocate_n(capacity());
+ m_size = other.size();
+ uninitialized_move_with_allocator(other.begin(), begin(), other.size());
+ other.clear();
+ return;
+ }
+ }
+ m_size = std::exchange(other.m_size, size_type{});
+ m_capacity = std::exchange(other.m_capacity, size_type{});
+ m_data = std::exchange(other.m_data, nullptr);
+ }
//! Construct a new vector and initialize it's content by copying all elements in the given initializer list.
//!
@@ -198,7 +215,7 @@ namespace kstd
return *this;
}
- if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
+ if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value)
{
if (get_allocator() != other.get_allocator())
{
@@ -529,13 +546,12 @@ namespace kstd
}
auto new_data = allocate_n(m_size);
- for (auto & element : *this)
- {
- std::allocator_traits<allocator_type>::construct(m_allocator, new_data++, std::move(element));
- }
+ auto old_size = size();
+ uninitialized_move_with_allocator(begin(), new_data, old_size);
clear_and_deallocate();
std::exchange(m_data, new_data);
- m_capacity = m_size;
+ m_capacity = old_size;
+ m_size = old_size;
}
//! Clear the contents of this vector.
@@ -551,7 +567,7 @@ namespace kstd
constexpr auto push_back(value_type const & value) -> void
{
increase_capacity_if_full();
- std::allocator_traits<allocator_type>::construct(m_allocator, &(*this)[m_size], value);
+ std::allocator_traits<allocator_type>::construct(m_allocator, data() + size(), value);
++m_size;
}
@@ -559,7 +575,7 @@ namespace kstd
constexpr auto push_back(value_type && value) -> void
{
increase_capacity_if_full();
- std::allocator_traits<allocator_type>::construct(m_allocator, &(*this)[m_size], std::move(value));
+ std::allocator_traits<allocator_type>::construct(m_allocator, data() + size(), std::move(value));
++m_size;
}
@@ -568,7 +584,7 @@ namespace kstd
constexpr auto emplace_back(Args &&... args) -> reference
{
increase_capacity_if_full();
- std::allocator_traits<allocator_type>::construct(m_allocator, &(*this)[m_size], std::forward<Args>(args)...);
+ std::allocator_traits<allocator_type>::construct(m_allocator, data() + size(), std::forward<Args>(args)...);
++m_size;
return this->back();
}
@@ -578,7 +594,8 @@ namespace kstd
//! If this vector is empty, the behavior is undefined.
auto pop_back() -> void
{
- std::allocator_traits<allocator_type>::destroy(m_allocator, &(*this)[--m_size]);
+ --m_size;
+ std::allocator_traits<allocator_type>::destroy(m_allocator, data() + size());
}
private:
@@ -601,7 +618,7 @@ namespace kstd
{
for (auto i = 0uz; i < count; ++i)
{
- *to++ = std::move(*from++);
+ *to++ = *from++;
}
}