From 6b658b55535670a54527b0b96597bce2ee2bd253 Mon Sep 17 00:00:00 2001 From: jyxiong Date: Thu, 25 Sep 2025 20:37:06 +0800 Subject: [PATCH] feat: impl assign function of vector --- source/tinystl/container/vector.h | 163 ++++++++++++++++++++++++++---- 1 file changed, 142 insertions(+), 21 deletions(-) diff --git a/source/tinystl/container/vector.h b/source/tinystl/container/vector.h index fdad7be..fb70d69 100644 --- a/source/tinystl/container/vector.h +++ b/source/tinystl/container/vector.h @@ -52,8 +52,13 @@ class vector { vector &operator=(std::initializer_list init); void assign(std::size_t n, const T &val); - template - void assign(InputIt first, InputIt last); + template + requires std::constructible_from> + void assign(ForwardIter first, ForwardIter last); + template + requires std::constructible_from> && + (!std::forward_iterator) + void assign(InputIter first, InputIter last); void assign(std::initializer_list ilist); allocator_type get_allocator() const; @@ -118,12 +123,18 @@ class vector { private: void throw_length_error(); + size_type recommend(size_type new_size); + void allocate(std::size_t n); + void deallocate(); + void construct(std::size_t n); - void construct(std::size_t n, const T& val); - template - void construct(InputIterator first, Sential last, std::size_t n); + void construct(std::size_t n, const T &val); + template + void construct(InputIter first, Sentinel last, std::size_t n); + + void destruct(pointer new_last); private: Alloc m_alloc; @@ -197,16 +208,14 @@ vector::vector( } template -template - requires std::constructible_from> && - (!std::forward_iterator) && +template + requires std::constructible_from> && + (!std::forward_iterator) && (std::movable || std::copyable) -vector::vector( - InputIterator first, InputIterator last, const Alloc &alloc -) { - static_assert( - true, "tinystl::vector does not support construction from input iterators." - ); +vector::vector(InputIter first, InputIter last, const Alloc &alloc) { + for (; first != last; ++first) { + this->emplace_back(*first); + } } template @@ -269,14 +278,94 @@ vector::vector(vector &&other, const Alloc &alloc) : m_alloc(alloc) { std::size_t n = other.size(); if (n > 0) { this->allocate(n); - this->construct(std::make_move_iterator(other.begin()), - std::make_move_iterator(other.end()), n); + this->construct( + std::make_move_iterator(other.begin()), + std::make_move_iterator(other.end()), n + ); } else { m_begin = m_end = m_cap = nullptr; } } } +template +vector::~vector() {} + +template +vector &vector::operator=(const vector &other) {} + +template +vector &vector::operator=(vector &&other) {} + +template +vector & +vector::operator=(std::initializer_list init) {} + +template +void vector::assign(std::size_t n, const T &val) { + if (n <= this->capacity()) { + size_type sz = this->size(); + std::fill_n(m_begin, std::min(n, sz), val); + if (n > sz) { + this->construct(n - sz, val); + } else { + this->destruct(m_begin + n); + } + } else { + this->destruct(m_begin); + this->deallocate(); + this->allocate(this->recommend(n)); + this->construct(n, val); + } +} + +template +template + requires std::constructible_from> +void vector::assign(ForwardIter first, ForwardIter last) { + size_type n = std::distance(first, last); + if (n <= this->capacity()) { + size_type sz = this->size(); + if (n > sz) { + ForwardIter mid = std::next(first, sz); + std::copy(first, mid, m_begin); + this->construct(mid, last, n - sz); + } else { + pointer new_last = std::copy(first, last, m_begin); + this->destruct(new_last); + } + } else { + this->destruct(m_begin); + this->deallocate(); + this->allocate(this->recommend(n)); + this->construct(first, last, n); + } +} + +template +template +requires std::constructible_from> && + (!std::forward_iterator) +void vector::assign(InputIter first, InputIter last) { + pointer cur = m_begin; + for (; cur != m_end && first != last; ++cur, ++first) { + *cur = *first; + } + + if (cur != m_end) { + this->destruct(cur); + } else { + for (; first != last; ++first) { + this->emplace_back(*first); + } + } +} + +template +void vector::assign(std::initializer_list init) { + assign(init.begin(), init.end()); +} + /* -------------------------------------------------------------------------- */ /* private member functions */ /* -------------------------------------------------------------------------- */ @@ -285,6 +374,22 @@ void vector::throw_length_error() { throw std::length_error("vector"); } +template +typename vector::size_type +vector::recommend(size_type new_size) { + const size_type max_size = this->max_size(); + if (new_size > max_size) { + this->throw_length_error(); + } + + const size_type cap = this->capacity(); + if (cap >= max_size / 2) { + return max_size; + } + + return std::max(2 * cap, new_size); +} + template void vector::allocate(std::size_t n) { if (n > this->max_size()) { @@ -295,6 +400,14 @@ void vector::allocate(std::size_t n) { } } +template +void vector::deallocate() { + if (m_begin != nullptr) { + alloc_traits::deallocate(m_alloc, m_begin, capacity()); + m_begin = m_end = m_cap = nullptr; + } +} + template void vector::construct(std::size_t n) { m_end = m_begin; @@ -305,7 +418,7 @@ void vector::construct(std::size_t n) { } template -void vector::construct(std::size_t n, const T& val) { +void vector::construct(std::size_t n, const T &val) { m_end = m_begin; for (std::size_t i = 0; i < n; ++i) { alloc_traits::construct(m_alloc, m_end, val); @@ -314,10 +427,9 @@ void vector::construct(std::size_t n, const T& val) { } template -template -void vector::construct( - InputIterator first, Sential last, std::size_t n -) { +template +void vector::construct(InputIter first, Sentinel last, std::size_t n) { + // FIXME: check last and n m_end = m_begin; for (std::size_t i = 0; i < n; ++i) { alloc_traits::construct(m_alloc, m_end, *first); @@ -325,4 +437,13 @@ void vector::construct( ++first; } } + +template +void vector::destruct(pointer new_last) { + pointer new_end = m_end; + while (new_last != new_end) { + alloc_traits::destroy(m_alloc, --new_end); + } + m_end = new_last; +} } // namespace tinystl