Factory function to create a vector with specified size and construction arguments.
Factory function to create a vector with specified size and construction arguments.
// Creates a vector of 10 default-constructed integers auto vec = makeVector<int>(10);
// Creates a vector of 5 strings initialized with "hello" auto strVec = makeVector<std::string>(5, "hello");
#ifndef VECTOR_H
#define VECTOR_H
template <typename TYPE, typename ALLOC = allocator<TYPE>>
class vector final : public baseList<TYPE, ALLOC>, public iterationStream<TYPE, vector<TYPE, ALLOC>>{
TYPE* body;
void vectorInit();
void vectorArrayDestruct() noexcept;
static void moveElements(TYPE* old_body,
u_integer inner_idx,
[[nodiscard]]
bool outOfMaxSize(
u_integer increment)
const;
public:
class Iterator final : public randomAccessIterator<TYPE, ALLOC>
{
public:
friend vector;
Iterator(const Iterator& other);
Iterator*
clone()
const override;
bool atPrev(
const iterator<TYPE> *other)
const override;
bool atNext(
const iterator<TYPE> *other)
const override;
[[nodiscard]] std::string
className()
const override;
};
explicit vector(ALLOC alloc = ALLOC{});
template<typename... ARGS>
vector(const vector& other);
vector(const std::initializer_list<TYPE>& list);
explicit vector(const array<TYPE>& arr);
vector(vector&& other) noexcept;
using serial<TYPE, ALLOC>::operator[];
void pushEnd(
const TYPE &e)
override;
Iterator*
begins()
const override;
Iterator*
ends()
const override;
[[nodiscard]] std::string
className()
const override;
template<typename T, typename... ARGS>
};
template<typename T, typename... ARGS>
vector<T> makeVector(
u_integer size, ARGS&&... args);
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::vectorInit() -> void
{
this->size_ = 0;
this->max_size = this->INNER_SIZE_INIT;
this->inner_begin = (this->INNER_SIZE_INIT - 1)/2;
this->body = vector::vectorArrayInit(this->INNER_SIZE_INIT);
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::vectorArrayDestruct() noexcept -> void
{
if (this->body) {
for (u_integer i = 0; i < this->max_size; ++i) {
this->destroy(&this->body[i]);
}
this->deallocate(this->body, this->max_size);
this->body = nullptr;
}
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::vectorArrayInit(const u_integer size) -> TYPE* {
auto arr = this->allocate(size);
for (u_integer i = 0; i < size; i++) {
this->construct(&arr[i]);
}
return arr;
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::moveElements(TYPE* old_body, const u_integer inner_idx,
const u_integer len, TYPE* new_body, const integer offset) -> void{
if (offset > 0)
{
for (u_integer i = 0; i < len; i += 1)
{
new_body[inner_idx + offset + len - 1 - i] = old_body[inner_idx + len - 1 - i];
}
}else
{
for (u_integer i = 0; i < len; i += 1)
{
new_body[inner_idx + offset + i] = old_body[inner_idx + i];
}
}
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::toInnerIdx(integer index)
const ->
u_integer
{
return this->inner_begin + index;
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::outOfMaxSize(u_integer increment) const -> bool
{
return this->inner_begin + this->size() + increment > this->max_size - 1 ||
static_cast<integer>(this->inner_begin) -
static_cast<integer>(increment) < 0;
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::grow(const u_integer new_size) -> void
{
TYPE* new_body = vector::vectorArrayInit(new_size);
vector::moveElements(this->body, this->inner_begin,
this->size(), new_body, offset);
this->vectorArrayDestruct();
this->body = new_body;
this->max_size = new_size;
this->inner_begin = new_begin;
}
template <typename TYPE, typename ALLOC>
auto original::vector<TYPE, ALLOC>::adjust(u_integer increment) -> void {
if (!this->outOfMaxSize(increment)) {
return;
}
u_integer new_begin = (this->max_size - this->size() - increment) / 2;
if (this->max_size >= this->size_ + increment && new_begin > 0) {
vector::moveElements(this->body, this->inner_begin, this->size(),
this->body, offset);
this->inner_begin = new_begin;
} else {
const u_integer new_max_size = (this->size() + increment) * 2;
this->grow(new_max_size);
}
}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::Iterator::Iterator(TYPE* ptr, const vector* container, integer pos)
: randomAccessIterator<TYPE, ALLOC>(ptr, container, pos) {}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::Iterator::Iterator(const Iterator& other)
: randomAccessIterator<TYPE, ALLOC>(nullptr, nullptr, 0)
{
this->operator=(other);
}
template <typename TYPE, typename ALLOC>
{
if (this == &other) {
return *this;
}
randomAccessIterator<TYPE, ALLOC>::operator=(other);
return *this;
}
template <typename TYPE, typename ALLOC>
return new Iterator(*this);
}
template <typename TYPE, typename ALLOC>
auto other_it =
dynamic_cast<const Iterator*
>(other);
return this->_ptr + 1 == other_it->
_ptr;
}
template <typename TYPE, typename ALLOC>
auto other_it =
dynamic_cast<const Iterator*
>(other);
return other_it->
_ptr + 1 == this->_ptr;
}
template <typename TYPE, typename ALLOC>
return "vector::Iterator";
}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::vector(ALLOC alloc)
: baseList<TYPE, ALLOC>(std::move(alloc)), size_(), max_size(), inner_begin()
{
this->vectorInit();
}
template<typename TYPE, typename ALLOC>
template<typename... ARGS>
original::vector<TYPE, ALLOC>::vector(u_integer size, ALLOC alloc, ARGS&&... args)
: vector(size, std::move(alloc)) {
this->body = this->allocate(this->max_size);
for (u_integer i = 0; i < this->size_; ++i) {
this->construct(&this->body[this->toInnerIdx(i)], std::forward<ARGS>(args)...);
}
}
template<typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::vector(const u_integer size, ALLOC alloc)
: baseList<TYPE, ALLOC>(std::move(alloc)), size_(size),
max_size(size * 4 / 3), inner_begin(size / 3 - 1), body(nullptr) {
}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::vector(const vector& other) : vector(){
this->operator=(other);
}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::vector(const std::initializer_list<TYPE>& list) : vector()
{
this->adjust(list.size());
for (const TYPE& e: list)
{
this->body[this->inner_begin + this->size()] = e;
this->size_ += 1;
}
}
template <typename TYPE, typename ALLOC>
{
if (this == &other)
return *this;
this->vectorArrayDestruct();
this->max_size = other.max_size;
this->inner_begin = other.inner_begin;
this->size_ = other.size_;
this->body = vector::vectorArrayInit(this->max_size);
for (u_integer i = 0; i < this->size(); ++i) {
const TYPE& data = other.body[this->toInnerIdx(i)];
this->body[this->toInnerIdx(i)] = data;
}
if constexpr (ALLOC::propagate_on_container_copy_assignment::value){
this->allocator = other.allocator;
}
return *this;
}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::vector(vector&& other) noexcept : vector()
{
this->operator=(std::move(other));
}
template <typename TYPE, typename ALLOC>
{
if (this == &other)
return *this;
this->vectorArrayDestruct();
this->body = other.body;
other.body = nullptr;
this->max_size = other.max_size;
this->inner_begin = other.inner_begin;
this->size_ = other.size_;
if constexpr (ALLOC::propagate_on_container_move_assignment::value){
this->allocator = std::move(other.allocator);
}
other.vectorInit();
return *this;
}
template <typename TYPE, typename ALLOC>
original::vector<TYPE, ALLOC>::vector(const array<TYPE>& arr) : vector()
{
this->adjust(arr.size());
for (u_integer i = 0; i < arr.size(); i += 1)
{
this->body[this->toInnerIdx(i)] = arr.get(i);
this->size_ += 1;
}
}
template <typename TYPE, typename ALLOC>
{
return this->size_;
}
template <typename TYPE, typename ALLOC>
return this->body[this->toInnerIdx(0)];
}
template <typename TYPE, typename ALLOC>
{
if (this->indexOutOfBound(index))
{
throw outOfBoundError();
}
index = this->toInnerIdx(this->parseNegIndex(index));
return this->body[index];
}
template <typename TYPE, typename ALLOC>
{
if (this->indexOutOfBound(index))
{
throw outOfBoundError();
}
index = this->toInnerIdx(this->parseNegIndex(index));
return this->body[index];
}
template <typename TYPE, typename ALLOC>
{
if (this->indexOutOfBound(index))
{
throw outOfBoundError();
}
index = this->toInnerIdx(this->parseNegIndex(index));
this->body[index] = e;
}
template <typename TYPE, typename ALLOC>
{
for (u_integer i = 0; i < this->size(); i += 1)
{
{
return i;
}
}
return this->size();
}
template <typename TYPE, typename ALLOC>
{
this->adjust(1);
this->inner_begin -= 1;
this->body[this->toInnerIdx(0)] = e;
this->size_ += 1;
}
template <typename TYPE, typename ALLOC>
{
if (this->parseNegIndex(index) == this->size())
{
this->pushEnd(e);
}else if (this->parseNegIndex(index) == 0)
{
this->pushBegin(e);
}else
{
if (this->indexOutOfBound(index))
{
throw outOfBoundError();
}
this->adjust(1);
index = this->toInnerIdx(this->parseNegIndex(index));
u_integer rel_idx = index - this->inner_begin;
if (index - this->inner_begin <= (this->size() - 1) / 2)
{
vector::moveElements(this->body, this->inner_begin,
rel_idx + 1, this->body, -1);
this->inner_begin -= 1;
}else
{
vector::moveElements(this->body, index,
this->size() - rel_idx, this->body, 1);
}
this->body[this->toInnerIdx(rel_idx)] = e;
this->size_ += 1;
}
}
template <typename TYPE, typename ALLOC>
{
this->adjust(1);
this->body[this->toInnerIdx(this->size())] = e;
this->size_ += 1;
}
template <typename TYPE, typename ALLOC>
{
if (this->size() == 0){
throw noElementError();
}
this->inner_begin += 1;
this->size_ -= 1;
return res;
}
template <typename TYPE, typename ALLOC>
{
if (this->parseNegIndex(index) == 0)
{
return this->popBegin();
}
if (this->parseNegIndex(index) == this->size() - 1)
{
return this->popEnd();
}
if (this->indexOutOfBound(index)){
throw outOfBoundError();
}
TYPE res = this->
get(index);
index = this->toInnerIdx(this->parseNegIndex(index));
u_integer rel_idx = index - this->inner_begin;
if (index - this->inner_begin <= (this->size() - 1) / 2)
{
vector::moveElements(this->body, this->inner_begin,
rel_idx, this->body, 1);
this->inner_begin += 1;
}else
{
vector::moveElements(this->body, index + 1,
this->size() - 1 - rel_idx, this->body, -1);
}
this->size_ -= 1;
return res;
}
template <typename TYPE, typename ALLOC>
{
if (this->size() == 0){
throw noElementError();
}
TYPE res = this->
get(this->size() - 1);
this->size_ -= 1;
return res;
}
template <typename TYPE, typename ALLOC>
return new Iterator(&this->body[this->toInnerIdx(0)], this, 0);
}
template <typename TYPE, typename ALLOC>
return new Iterator(&this->body[this->toInnerIdx(this->size() - 1)], this, this->size() - 1);
}
template <typename TYPE, typename ALLOC>
{
return "vector";
}
template <typename TYPE, typename ALLOC>
this->vectorArrayDestruct();
}
template<typename T, typename... ARGS>
}
#endif
Provides the array class for a fixed-size container with random access.
Provides a base class for variable-size serial containers.
Default memory allocator using allocators utilities.
Definition allocator.h:154
container(ALLOC alloc=ALLOC{})
Constructs a container with specified allocator.
Definition container.h:129
TYPE * _ptr
Pointer to the current element.
Definition randomAccessIterator.h:41
Random access iterator implementation for vector.
Definition vector.h:163
Iterator * clone() const override
Clones the iterator.
Definition vector.h:521
Iterator & operator=(const Iterator &other)
Assignment operator for the iterator.
Definition vector.h:511
std::string className() const override
Gets the class name of the iterator.
Definition vector.h:538
bool atNext(const iterator< TYPE > *other) const override
Checks if the iterator is at the next element relative to another iterator.
Definition vector.h:532
bool atPrev(const iterator< TYPE > *other) const override
Checks if the iterator is at the previous element relative to another iterator.
Definition vector.h:526
Dynamic array container with amortized constant time operations.
Definition vector.h:43
u_integer size() const override
Gets the size of the vector.
Definition vector.h:640
vector & operator=(const vector &other)
Assignment operator for the vector.
Definition vector.h:582
TYPE popBegin() override
Removes and returns the first element in the vector.
Definition vector.h:747
TYPE & data() const
Gets a reference to the first element in the vector.
Definition vector.h:646
void push(integer index, const TYPE &e) override
Inserts an element at the specified index in the vector.
Definition vector.h:706
~vector() override
Destructor for the vector.
Definition vector.h:817
Iterator * ends() const override
Gets an iterator to the end of the vector.
Definition vector.h:806
void pushEnd(const TYPE &e) override
Inserts an element at the end of the vector.
Definition vector.h:739
void pushBegin(const TYPE &e) override
Inserts an element at the beginning of the vector.
Definition vector.h:697
std::string className() const override
Gets the class name of the vector.
Definition vector.h:811
TYPE pop(integer index) override
Removes and returns the element at the specified index.
Definition vector.h:759
u_integer indexOf(const TYPE &e) const override
Finds the index of the first occurrence of the specified element.
Definition vector.h:684
TYPE get(integer index) const override
Gets an element at the specified index.
Definition vector.h:651
void set(integer index, const TYPE &e) override
Sets the element at the specified index.
Definition vector.h:673
Iterator * begins() const override
Gets an iterator to the beginning of the vector.
Definition vector.h:801
TYPE & operator[](integer index) override
Gets a reference to the element at the specified index.
Definition vector.h:662
TYPE popEnd() override
Removes and returns the last element in the vector.
Definition vector.h:790
constexpr auto & get(original::couple< F, S > &c) noexcept
Structured binding support - get for non-const lvalue reference.
Definition couple.h:364
Provides functionality for an iteration stream.
Main namespace for the project Original.
Definition algorithms.h:21
std::uint32_t u_integer
32-bit unsigned integer type for sizes and indexes
Definition config.h:43
std::int64_t integer
64-bit signed integer type for arithmetic operations
Definition config.h:35