7#include <initializer_list>
13 template <
typename Strategy>
15 std::default_initializable<Strategy> &&
16 noexcept(Strategy()) &&
17 requires(Strategy strategy, std::size_t num) {
18 { strategy(num) } -> std::same_as<std::size_t>;
24 return oldCapacity + oldCapacity / 2 + 1;
30 return oldCapacity * 2 + 1;
39 std::size_t n3 =
n1 +
n2;
42 }
while (
n2 <= oldCapacity);
48 template <
typename T,
typename Allocator = PolymorphicAllocator<>, GrowthStrategy Strategy = VectorGrowthStrategy::GoldenExpand>
60 using allocator_type = std::allocator_traits<Allocator>::template rebind_alloc<T>;
63 using allocator_trait = std::allocator_traits<Allocator>::template rebind_traits<T>;
109 :
Vector(std::move(rhs), rhs.get_allocator()) {
120 if (rhs.get_allocator() == allocator) {
124 Vector rhsCopy(rhs, allocator);
125 swap(*this, rhsCopy);
134 template <std::input_iterator It>
138 size_(std::distance(first, last)),
183 noexcept(std::is_nothrow_swappable_v<Vector>) {
189 assert(i <
size_ &&
"index out of bound");
194 assert(i <
size_ &&
"index out of bound");
223 constexpr std::size_t
size() const noexcept {
235 constexpr bool empty() const noexcept {
242 assert(0 <
size_ &&
"access empty Vector front");
248 constexpr const T&
front() const noexcept {
249 assert(0 <
size_ &&
"access empty Vector front");
256 assert(0 <
size_ &&
"access empty Vector back");
262 constexpr const T&
back() const noexcept {
263 assert(0 <
size_ &&
"access empty Vector back");
310 template <
typename ...Args>
321 assert(0 <
size_ &&
"can not pop back from an empty vector");
330 assert(
begin() <= pos && pos <
end() &&
"can not erase before begin() or at the end()");
331 std::move(pos + 1,
end(), pos);
341 assert(
begin() <= first && last <=
end() &&
"can not erase before begin() or past the end()");
342 assert(first <= last &&
"first must be before last");
344 iterator afterMoved = std::move(last,
end(), first);
346 size_ -= last - first;
353 template <
typename ...Args>
365 std::move_backward(pos,
end() - 1,
end());
366 *pos = T(std::forward<Args>(args)...);
370 std::size_t index = pos -
buffer_;
372 allocator_trait::construct(
allocator_,
buffer_ + index, std::forward<Args>(args)...);
388 emplace(pos, std::move(value));
405 template <std::input_iterator It>
407 const std::size_t insertedElementsSize = std::distance(first, last);
408 const std::size_t requiredSize =
size_ + insertedElementsSize;
412 std::size_t index = pos -
begin();
419 const std::size_t shiftedElementSize =
end() - pos;
420 const std::size_t conflictedRangeSize = std::min(insertedElementsSize, shiftedElementSize);
421 const std::size_t shiftedElementsInboundSize = shiftedElementSize - conflictedRangeSize;
422 const std::size_t insertedElementsOutboundSize = insertedElementsSize - conflictedRangeSize;
430 std::move_backward(pos, pos + shiftedElementsInboundSize,
end());
434 for (std::size_t i = 0; i < conflictedRangeSize; ++i, ++first, ++pos) {
444 size_ = requiredSize;
451 insert(pos, list.begin(), list.end());
465 assert(
capacity_ <
capacity &&
"new capacity is no larger than the old capacity");
474 assert(
capacity_ <
capacity &&
"new capacity is no larger than the old capacity");
482 template <
typename ...U>
484 static_assert(
sizeof...(optionalValue) <= 1,
"no fill value or exactly one copy");
502 swap(lhs.allocator_, rhs.allocator_);
503 swap(lhs.growthStrategy_, rhs.growthStrategy_);
504 swap(lhs.size_, rhs.size_);
505 swap(lhs.capacity_, rhs.capacity_);
506 swap(lhs.buffer_, rhs.buffer_);
513 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
518 return !(lhs == rhs);
Iterator that returns a constant value a fixed number of times. Useful for creating a virtual range o...
void insert(iterator pos, It first, It last)
Inserts a range of elements at the specified position. Does not support self-insertion.
allocator_type get_allocator() const noexcept
void emplaceBack(Args &&... args)
Constructs an element in-place at the end of the vector.
constexpr std::size_t size() const noexcept
Returns the number of elements in the vector.
constexpr Vector(Vector &&rhs) noexcept
Move-constructs a vector with the same allocator as the source.
iterator erase(iterator first, iterator last) noexcept
Removes elements in the range [first, last).
constexpr const T & back() const noexcept
Returns a reference to the last element.
constexpr Vector(Vector &&rhs, const allocator_type &allocator)
Move-constructs a vector with a custom allocator.
std::allocator_traits< Allocator >::template rebind_traits< T > allocator_trait
void pushBack(const T &value)
Adds an element to the end of the vector.
iterator begin() noexcept
void relocateBufferWithHoles(std::size_t capacity, iterator pos, std::size_t holeSize)
constexpr Vector(const Vector &rhs)
Copy-constructs a vector using the same allocator as the source.
constexpr std::size_t capacity() const noexcept
Returns the total allocated capacity.
VectorGrowthStrategy::GoldenExpand growthStrategy_
void emplace(iterator pos, Args &&... args)
Constructs an element in-place at the specified iterator position.
constexpr Vector(std::size_t count, const allocator_type &allocator={})
Constructs a vector with count default-initialized elements.
iterator erase(iterator pos) noexcept
Removes an element at the specified iterator position.
void pushBack(T &&value)
Adds an element to the end of the vector.
void insert(iterator pos, T &&value)
Inserts a moved element at the specified iterator position.
T & operator[](std::size_t i) noexcept
constexpr Vector(std::size_t count, const T &value, const allocator_type &allocator={})
Constructs a vector with count copies of a given value.
void resize(std::size_t size, const T &value)
Resizes the vector and fills new elements with a given value.
constexpr Vector(const allocator_type &allocator) noexcept(noexcept(allocator_type(allocator)))
Constructs an empty vector with a specific allocator.
void resizeImp(std::size_t size, const U &... optionalValue)
const T & operator[](std::size_t i) const noexcept
void relocateBuffer(std::size_t capacity)
void updateBuffer(T *buffer, std::size_t capacity)
constexpr const T & front() const noexcept
Returns a reference to the first element.
constexpr Vector(It first, It last, const allocator_type &allocator={})
Constructs a vector from an iterator range.
T & front() noexcept
Returns a reference to the first element.
void resize(std::size_t size)
Resizes the vector to contain the given number of default constructed elements.
const T & const_reference
void insert(iterator pos, std::size_t count, const T &value)
Inserts multiple copies of a value at the specified position.
void insert(iterator pos, std::initializer_list< T > list)
Inserts an initializer list of elements at the specified position.
friend void swap(Vector &lhs, Vector &rhs) noexcept
T & back() noexcept
Returns a reference to the last element.
allocator_type allocator_
Vector & operator=(Vector rhs) noexcept(std::is_nothrow_swappable_v< Vector >)
constexpr bool empty() const noexcept
Checks whether the vector is empty.
constexpr const_iterator end() const noexcept
std::ptrdiff_t difference_type
std::allocator_traits< Allocator >::template rebind_alloc< T > allocator_type
constexpr Vector(std::initializer_list< T > list, const allocator_type &allocator={})
Constructs a vector from an initializer list.
void popBack() noexcept
Removes the last element of the vector.
void clear() noexcept
Clears the contents of the vector.
constexpr Vector(const Vector &rhs, const allocator_type &allocator)
Copy-constructs a vector with a custom allocator.
constexpr Vector() noexcept
Constructs an empty vector with default allocator and growth strategy.
constexpr const_iterator begin() const noexcept
void reserve(std::size_t capacity)
Ensures the vector can hold at least the given capacity without reallocating.
void insert(iterator pos, const T &value)
Inserts a copy of an element at the specified iterator position.
bool operator!=(const flow::Vector< T > &lhs, const flow::Vector< T > &rhs) noexcept
bool operator==(const flow::Vector< T > &lhs, const flow::Vector< T > &rhs) noexcept
OutputIt uninitializedEmplace(AllocatorType &allocator, OutputIt first, OutputIt last, const Args &... args)
Constructs objects in uninitialized memory by copying arguments to their constructor....
void destroyElements(AllocatorType &allocator, InputIt first, InputIt last) noexcept
Destroys a range of constructed objects in memory.
void destroyElementsN(AllocatorType &allocator, InputIt first, std::size_t count) noexcept
Destroys count objects in a range.
OutputIt uninitializedMove(AllocatorType &allocator, InputIt first, InputIt last, OutputIt dest) noexcept
Moves elements from a source range to uninitialized memory.
OutputIt uninitializedFillN(AllocatorType &allocator, OutputIt first, std::size_t count, const T &value)
Fills count elements in uninitialized memory with a value.
OutputIt uninitializedForwardN(AllocatorType &allocator, InputIt first, std::size_t count, OutputIt dest)
Forward count elements from a source range to uninitialized memory.
OutputIt uninitializedForward(AllocatorType &allocator, InputIt first, InputIt last, OutputIt dest)
Forward elements from a source range to uninitialized memory.
void deleteBuffer(AllocatorType &allocator, T *buffer, std::size_t size, std::size_t capacity) noexcept
Destroys and deallocates the buffer.
OutputIt uninitializedEmplaceN(AllocatorType &allocator, OutputIt first, std::size_t count, const Args &... args)
Constructs a specified number of objects in uninitialized memory by copying constructor arguments....
std::size_t operator()(std::size_t oldCapacity) const
std::size_t operator()(std::size_t oldCapacity)
std::size_t operator()(std::size_t oldCapacity) const