diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-19 13:54:37 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-03-19 13:54:37 +0100 |
| commit | b038db886fd1e2179f543217f5d3ed7b8d964c4a (patch) | |
| tree | 82d6ab45d5e3770d9b724f36558c2f6a64a789e0 /libs | |
| parent | 584304d99b6bb43cef8aab9c6bfe22d24a5bf5a0 (diff) | |
| download | teachos-b038db886fd1e2179f543217f5d3ed7b8d964c4a.tar.xz teachos-b038db886fd1e2179f543217f5d3ed7b8d964c4a.zip | |
kstd: fix vector bugs
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/kstd/include/kstd/vector | 53 |
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++; } } |
