Skip to content

Instantly share code, notes, and snippets.

@bkrmendy
Last active March 16, 2023 13:50
Show Gist options
  • Save bkrmendy/d7d5b0416b997b562f1c3c2275b5a4ec to your computer and use it in GitHub Desktop.
Save bkrmendy/d7d5b0416b997b562f1c3c2275b5a4ec to your computer and use it in GitHub Desktop.
vector
#include <stdexcept>
#include <iostream>
#include <initializer_list>
template <typename T>
class Vector
{
static constexpr std::size_t min_capacity = 8;
public:
class Iterator;
class ConstIterator;
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using reference = value_type &;
using const_reference = const value_type &;
using pointer = value_type *;
using const_pointer = const value_type *;
using iterator = Vector::Iterator;
using const_iterator = Vector::ConstIterator;
private:
size_type size_ = 0;
size_type max_size_ = 0;
value_type *values_ = nullptr;
void realloc(size_type next_size)
{
size_type new_size = std::max(this->size_, next_size);
value_type *new_values = new value_type[new_size];
for (size_type idx = 0; idx < this->size_; idx++)
{
new_values[idx] = this->values_[idx];
}
if (this->values_ != nullptr)
{
delete[] this->values_;
}
this->max_size_ = new_size;
this->values_ = new_values;
}
public:
Vector() : size_{0}
{
this->realloc(min_capacity);
}
Vector(std::size_t desired_size) : size_{0}
{
this->realloc(std::max(desired_size, min_capacity));
}
Vector(const Vector &other)
{
this->realloc(other.size());
this->clear();
for (auto value : other)
{
this->push_back(value);
}
}
Vector(std::initializer_list<Vector::value_type> initial)
{
this->realloc(std::max(initial.size(), min_capacity));
for (auto value : initial)
{
this->push_back(value);
}
}
Vector &operator=(const Vector &other)
{
if (this == &other)
{
return *this;
}
this->realloc(other.size());
this->clear();
for (auto value : other)
{
this->push_back(value);
}
return *this;
}
~Vector()
{
delete[] values_;
}
size_type size() const
{
return this->size_;
}
size_type capacity() const
{
return this->max_size_;
}
bool empty() const
{
return this->size_ == 0;
}
void clear()
{
this->size_ = 0;
}
void reserve(size_type desired_size)
{
this->realloc(desired_size);
}
void shrink_to_fit()
{
this->realloc(this->size_);
}
void push_back(value_type value)
{
if (this->size_ >= this->max_size_)
{
this->realloc(this->max_size_ * 2);
}
this->values_[this->size_] = value;
this->size_ += 1;
}
void pop_back()
{
if (this->empty())
{
throw std::runtime_error("Popping empty Vector");
}
this->size_ -= 1;
}
value_type &operator[](size_type index)
{
if (index < this->size_)
{
return this->values_[index];
}
throw std::runtime_error("Index out of range");
}
const value_type &operator[](size_type index) const
{
if (index < this->size_)
{
return this->values_[index];
}
throw std::runtime_error("Index out of range");
}
iterator begin()
{
return Iterator{this->values_};
}
iterator end()
{
return Iterator{this->values_ + this->size_};
}
const_iterator begin() const
{
return ConstIterator{this->values_};
}
const_iterator end() const
{
return ConstIterator{this->values_ + this->size_};
}
iterator insert(const_iterator pos, const_reference val)
{
auto diff = pos - (const_iterator)begin();
if (diff < 0 || static_cast<size_type>(diff) > this->size_)
{
throw std::runtime_error("insert: Iterator out of bounds");
}
size_type current{static_cast<size_type>(diff)};
if (this->size_ >= this->max_size_)
{
reserve(this->max_size_ * 2 + 1);
}
for (auto i{this->size_}; i-- > current;)
{
this->values_[i + 1] = this->values_[i];
}
this->values_[current] = val;
++this->size_;
return iterator{this->values_ + current};
}
iterator erase(const_iterator pos)
{
auto diff = pos - begin();
if (diff < 0 || static_cast<size_type>(diff) > this->size_)
{
throw std::runtime_error("erase: Iterator out of bounds");
}
size_type current{static_cast<size_type>(diff)};
for (auto i{current}; i < this->size_ - 1; ++i)
{
this->values_[i] = this->values_[i + 1];
}
--this->size_;
return iterator{this->values_ + current};
}
class Iterator
{
using value_type = Vector::value_type;
using reference = Vector::reference;
using pointer = Vector::pointer;
using difference_type = Vector::difference_type;
using iterator_category = std::forward_iterator_tag;
private:
Vector::pointer elem_;
public:
Iterator() : elem_{nullptr} {}
Iterator(Vector::pointer elem) : elem_{elem} {}
Iterator &operator=(const Iterator &other)
{
this->elem_ = other.elem_;
return *this;
}
reference operator*()
{
if (this->elem_ == nullptr)
{
throw std::runtime_error("");
}
return *(this->elem_);
}
pointer operator->()
{
if (this->elem_ == nullptr)
{
throw std::runtime_error("");
}
return this->elem_;
}
iterator &operator++()
{
this->elem_++;
return *this;
}
iterator operator++(int)
{
Iterator temp = *this;
this->elem_++;
return temp;
}
friend bool operator==(const Iterator &lhs, const Iterator &rhs)
{
return lhs.elem_ == rhs.elem_;
}
friend bool operator!=(const Iterator &lhs, const Iterator &rhs)
{
return !(lhs == rhs);
}
operator const_iterator() const
{
return ConstIterator{this->elem_};
}
};
class ConstIterator
{
using value_type = Vector::value_type;
using reference = Vector::reference;
using pointer = Vector::pointer;
using difference_type = Vector::difference_type;
using iterator_category = std::forward_iterator_tag;
private:
Vector::pointer elem_;
public:
ConstIterator() : elem_{nullptr} {}
ConstIterator(Vector::pointer elem) : elem_{elem} {}
ConstIterator &operator=(const ConstIterator &other)
{
this->elem_ = other.elem_;
return *this;
}
const_reference operator*() const
{
if (this->elem_ == nullptr)
{
throw std::runtime_error("");
}
return *(this->elem_);
}
const_pointer operator->() const
{
if (this->elem_ == nullptr)
{
throw std::runtime_error("");
}
return this->elem_;
}
const_iterator &operator++()
{
this->elem_++;
return *this;
}
const_iterator operator++(int)
{
ConstIterator temp = *this;
++(*this);
return temp;
}
friend bool operator==(const ConstIterator &lhs, const ConstIterator &rhs)
{
return lhs.elem_ == rhs.elem_;
}
friend bool operator!=(const ConstIterator &lhs, const ConstIterator &rhs)
{
return !(lhs == rhs);
}
friend Vector::difference_type operator-(const Vector::ConstIterator &lop, const Vector::ConstIterator &rop)
{
return (*lop) - (*rop);
}
};
};
template <typename T>
std::ostream &operator<<(std::ostream &os, const Vector<T> &vector)
{
os << '[';
for (const auto value : vector)
{
os << value;
os << ' ';
}
os << ']';
return os;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment