add dynamically sized vector from usu c++ assignment.
This commit is contained in:
parent
205bddb307
commit
c6176c0591
311
inc/vector.hpp
Normal file
311
inc/vector.hpp
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
|
||||||
|
#ifndef USU_VECTOR_HPP
|
||||||
|
#define USU_VECTOR_HPP
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace usu {
|
||||||
|
template <typename T> class vector {
|
||||||
|
public:
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using reference = T &;
|
||||||
|
using pointer = std::shared_ptr<T[]>;
|
||||||
|
using value_type = T;
|
||||||
|
using resize_type = std::function<size_type(size_type)>;
|
||||||
|
|
||||||
|
static resize_type DEFAULT_RESIZER;
|
||||||
|
static size_type DEFAULT_CAPACITY;
|
||||||
|
|
||||||
|
vector();
|
||||||
|
vector(size_type size);
|
||||||
|
vector(resize_type resize);
|
||||||
|
vector(std::initializer_list<T> list);
|
||||||
|
vector(size_type size, resize_type resize);
|
||||||
|
vector(std::initializer_list<T> list, resize_type resize);
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
iterator();
|
||||||
|
iterator(pointer data);
|
||||||
|
iterator(size_type pos, pointer data);
|
||||||
|
iterator(const iterator &obj);
|
||||||
|
iterator(iterator &&obj) noexcept;
|
||||||
|
|
||||||
|
iterator &operator=(const iterator &rhs);
|
||||||
|
iterator &operator=(iterator &&rhs);
|
||||||
|
bool operator==(const iterator &rhs) const;
|
||||||
|
bool operator!=(const iterator &rhs) const;
|
||||||
|
iterator operator++();
|
||||||
|
iterator operator--();
|
||||||
|
iterator operator++(int);
|
||||||
|
iterator operator--(int);
|
||||||
|
value_type operator*();
|
||||||
|
std::shared_ptr<T> operator->();
|
||||||
|
|
||||||
|
private:
|
||||||
|
pointer m_data;
|
||||||
|
size_type m_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
reference operator[](size_type index);
|
||||||
|
void add(T value);
|
||||||
|
void insert(size_type index, T value);
|
||||||
|
void remove(size_type index);
|
||||||
|
void clear();
|
||||||
|
size_type size();
|
||||||
|
size_type capacity();
|
||||||
|
iterator begin();
|
||||||
|
iterator end();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
pointer m_data;
|
||||||
|
size_type m_capacity;
|
||||||
|
size_type m_size;
|
||||||
|
resize_type m_resize;
|
||||||
|
|
||||||
|
void maybe_resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> class vector<bool> : public vector<std::uint8_t> {
|
||||||
|
public:
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using pointer = std::shared_ptr<std::uint8_t[]>;
|
||||||
|
using resize_type = std::function<size_type(size_type)>;
|
||||||
|
|
||||||
|
vector();
|
||||||
|
vector(size_type size);
|
||||||
|
vector(resize_type resize);
|
||||||
|
vector(std::initializer_list<bool> list);
|
||||||
|
vector(size_type size, resize_type resize);
|
||||||
|
vector(std::initializer_list<bool> list, resize_type resize);
|
||||||
|
|
||||||
|
class reference {
|
||||||
|
public:
|
||||||
|
reference();
|
||||||
|
reference(size_type pos, pointer data);
|
||||||
|
reference &operator=(bool value);
|
||||||
|
operator bool();
|
||||||
|
bool operator==(const reference &rhs) const;
|
||||||
|
bool operator!=(const reference &rhs) const;
|
||||||
|
|
||||||
|
bool get() const;
|
||||||
|
void add();
|
||||||
|
void sub();
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_type m_pos;
|
||||||
|
pointer m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
public:
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
iterator();
|
||||||
|
iterator(pointer data);
|
||||||
|
iterator(size_type pos, pointer data);
|
||||||
|
iterator(const iterator &obj);
|
||||||
|
iterator(iterator &&obj) noexcept;
|
||||||
|
|
||||||
|
iterator &operator=(const iterator &rhs);
|
||||||
|
iterator &operator=(iterator &&rhs);
|
||||||
|
bool operator==(const iterator &rhs) const;
|
||||||
|
bool operator!=(const iterator &rhs) const;
|
||||||
|
iterator operator++();
|
||||||
|
iterator operator--();
|
||||||
|
iterator operator++(int);
|
||||||
|
iterator operator--(int);
|
||||||
|
reference operator*();
|
||||||
|
|
||||||
|
private:
|
||||||
|
reference m_ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
reference operator[](size_type index);
|
||||||
|
|
||||||
|
void add(bool value);
|
||||||
|
void insert(size_type index, bool value);
|
||||||
|
void remove(size_type index);
|
||||||
|
|
||||||
|
iterator begin();
|
||||||
|
iterator end();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void maybe_resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::iterator::iterator() : vector<T>::iterator::iterator(nullptr) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::iterator::iterator(pointer data) : m_data(data), m_pos(0) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::iterator::iterator(size_type pos, pointer data)
|
||||||
|
: m_data(data), m_pos(pos) {}
|
||||||
|
|
||||||
|
template <typename T> vector<T>::iterator::iterator(const iterator &obj) {
|
||||||
|
m_pos = obj.m_pos;
|
||||||
|
m_data = obj.m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> vector<T>::iterator::iterator(iterator &&obj) noexcept {
|
||||||
|
m_pos = obj.m_pos;
|
||||||
|
m_data = obj.m_data;
|
||||||
|
obj.m_pos = 0;
|
||||||
|
obj.m_data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool vector<T>::iterator::operator!=(const iterator &rhs) const {
|
||||||
|
return m_pos != rhs.m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool vector<T>::iterator::operator==(const iterator &rhs) const {
|
||||||
|
return m_pos == rhs.m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::iterator vector<T>::iterator::operator++() {
|
||||||
|
m_pos++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::iterator vector<T>::iterator::operator--() {
|
||||||
|
m_pos--;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::iterator vector<T>::iterator::operator++(int) {
|
||||||
|
iterator it = *this;
|
||||||
|
m_pos++;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::iterator vector<T>::iterator::operator--(int) {
|
||||||
|
iterator it = *this;
|
||||||
|
m_pos--;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::value_type vector<T>::iterator::operator*() {
|
||||||
|
return m_data[m_pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> std::shared_ptr<T> vector<T>::iterator::operator->() {
|
||||||
|
return std::make_shared<T>(m_data[m_pos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::resize_type vector<T>::DEFAULT_RESIZER =
|
||||||
|
[](size_type currentCapacity) -> size_type { return currentCapacity * 2; };
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::size_type vector<T>::DEFAULT_CAPACITY = 10;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::vector() : usu::vector<T>(0, DEFAULT_RESIZER) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
usu::vector<T>::vector(size_type size)
|
||||||
|
: usu::vector<T>(size, DEFAULT_RESIZER) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::vector(resize_type resize) : usu::vector<T>(0, resize) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::vector(std::initializer_list<T> list)
|
||||||
|
: usu::vector<T>(list, DEFAULT_RESIZER) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::vector(std::initializer_list<T> list, resize_type resize)
|
||||||
|
: usu::vector<T>(0, resize) {
|
||||||
|
for (auto i = list.begin(); i < list.end(); ++i)
|
||||||
|
add(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
vector<T>::vector(size_type size, resize_type resize)
|
||||||
|
: m_data(nullptr),
|
||||||
|
m_capacity(DEFAULT_CAPACITY > size ? DEFAULT_CAPACITY
|
||||||
|
: DEFAULT_RESIZER(size)),
|
||||||
|
m_size(size), m_resize(resize) {
|
||||||
|
maybe_resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void vector<T>::maybe_resize() {
|
||||||
|
if (m_data == nullptr)
|
||||||
|
m_data = std::make_shared<T[]>(m_capacity);
|
||||||
|
if (m_size >= m_capacity) {
|
||||||
|
m_capacity = std::max(m_capacity == 0 ? 1 : m_resize(m_capacity), m_size);
|
||||||
|
|
||||||
|
pointer newData = std::make_shared<T[]>(m_capacity);
|
||||||
|
for (size_type i = 0; i < m_size; ++i)
|
||||||
|
newData[i] = m_data[i];
|
||||||
|
|
||||||
|
m_data = newData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void vector<T>::add(T value) {
|
||||||
|
maybe_resize();
|
||||||
|
m_data[m_size++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename vector<T>::reference vector<T>::operator[](size_type index) {
|
||||||
|
return m_data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void vector<T>::insert(size_type index, T value) {
|
||||||
|
maybe_resize();
|
||||||
|
|
||||||
|
for (size_type i = m_size; i > index; --i)
|
||||||
|
m_data[i] = m_data[i - 1];
|
||||||
|
m_data[index] = value;
|
||||||
|
|
||||||
|
m_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void vector<T>::remove(size_type index) {
|
||||||
|
for (size_type i = index; i < m_size; ++i)
|
||||||
|
m_data[i] = m_data[i + 1];
|
||||||
|
m_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> typename vector<T>::iterator vector<T>::begin() {
|
||||||
|
vector<T>::iterator begin(m_data);
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> typename vector<T>::iterator vector<T>::end() {
|
||||||
|
vector<T>::iterator end(m_size, m_data);
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void vector<T>::clear() { m_size = 0; }
|
||||||
|
|
||||||
|
template <typename T> typename vector<T>::size_type vector<T>::size() {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> typename vector<T>::size_type vector<T>::capacity() {
|
||||||
|
return m_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace usu
|
||||||
|
|
||||||
|
#endif
|
171
src/vector.cpp
Normal file
171
src/vector.cpp
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#include "vector.hpp"
|
||||||
|
|
||||||
|
usu::vector<bool>::reference::reference()
|
||||||
|
: usu::vector<bool>::reference(0, nullptr) {}
|
||||||
|
|
||||||
|
usu::vector<bool>::reference::reference(size_type pos, pointer data)
|
||||||
|
: m_pos(pos), m_data(data) {}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::reference &
|
||||||
|
usu::vector<bool>::reference::operator=(bool value) {
|
||||||
|
std::uint8_t mask = 1 << (7 - (m_pos % 8));
|
||||||
|
if (value)
|
||||||
|
m_data[m_pos / 8] |= mask;
|
||||||
|
else
|
||||||
|
m_data[m_pos / 8] &= (~mask);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::reference
|
||||||
|
usu::vector<bool>::operator[](size_type index) {
|
||||||
|
reference r(index, m_data);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usu::vector<bool>::reference::add() { m_pos++; }
|
||||||
|
|
||||||
|
void usu::vector<bool>::reference::sub() { m_pos--; }
|
||||||
|
|
||||||
|
bool usu::vector<bool>::reference::get() const {
|
||||||
|
return ((m_data[m_pos / 8] >> (7 - (m_pos % 8))) & 1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
usu::vector<bool>::reference::operator bool() { return get(); }
|
||||||
|
|
||||||
|
bool usu::vector<bool>::reference::operator==(const reference &rhs) const {
|
||||||
|
return m_data == rhs.m_data && m_pos == rhs.m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool usu::vector<bool>::reference::operator!=(const reference &rhs) const {
|
||||||
|
return m_data != rhs.m_data || m_pos != rhs.m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
usu::vector<bool>::iterator::iterator()
|
||||||
|
: usu::vector<bool>::iterator(nullptr) {}
|
||||||
|
|
||||||
|
usu::vector<bool>::iterator::iterator(pointer data)
|
||||||
|
: usu::vector<bool>::iterator(0, data) {}
|
||||||
|
|
||||||
|
usu::vector<bool>::iterator::iterator(size_type pos, pointer data) {
|
||||||
|
m_ref = reference(pos, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
usu::vector<bool>::iterator::iterator(const iterator &obj) {
|
||||||
|
m_ref = obj.m_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
usu::vector<bool>::iterator::iterator(iterator &&obj) noexcept {
|
||||||
|
m_ref = obj.m_ref;
|
||||||
|
obj.m_ref = reference(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::iterator usu::vector<bool>::iterator::operator++() {
|
||||||
|
m_ref.add();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::iterator usu::vector<bool>::iterator::operator--() {
|
||||||
|
m_ref.sub();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::iterator
|
||||||
|
usu::vector<bool>::iterator::operator++(int) {
|
||||||
|
iterator it = *this;
|
||||||
|
m_ref.add();
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::iterator
|
||||||
|
usu::vector<bool>::iterator::operator--(int) {
|
||||||
|
iterator it = *this;
|
||||||
|
m_ref.sub();
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::reference usu::vector<bool>::iterator::operator*() {
|
||||||
|
return m_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool usu::vector<bool>::iterator::operator!=(const iterator &rhs) const {
|
||||||
|
return m_ref != rhs.m_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool usu::vector<bool>::iterator::operator==(const iterator &rhs) const {
|
||||||
|
return m_ref == rhs.m_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
usu::vector<bool>::vector() : usu::vector<bool>(0, DEFAULT_RESIZER){};
|
||||||
|
|
||||||
|
usu::vector<bool>::vector(size_type size)
|
||||||
|
: usu::vector<bool>(size, DEFAULT_RESIZER){};
|
||||||
|
|
||||||
|
usu::vector<bool>::vector(resize_type resize) : usu::vector<bool>(0, resize){};
|
||||||
|
|
||||||
|
usu::vector<bool>::vector(size_type size, resize_type resize) {
|
||||||
|
m_resize = resize;
|
||||||
|
m_size = size;
|
||||||
|
m_capacity = DEFAULT_CAPACITY > size ? DEFAULT_CAPACITY : resize(size);
|
||||||
|
maybe_resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
usu::vector<bool>::vector(std::initializer_list<bool> list)
|
||||||
|
: usu::vector<bool>(list, DEFAULT_RESIZER){};
|
||||||
|
|
||||||
|
usu::vector<bool>::vector(std::initializer_list<bool> list, resize_type resize)
|
||||||
|
: usu::vector<std::uint8_t>(0, resize) {
|
||||||
|
for (auto i = list.begin(); i != list.end(); ++i)
|
||||||
|
add(*i);
|
||||||
|
};
|
||||||
|
|
||||||
|
void usu::vector<bool>::add(bool value) {
|
||||||
|
maybe_resize();
|
||||||
|
reference r(m_size++, m_data);
|
||||||
|
r = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usu::vector<bool>::insert(size_type index, bool value) {
|
||||||
|
maybe_resize();
|
||||||
|
|
||||||
|
reference r1(m_size, m_data);
|
||||||
|
reference r2(m_size == 0 ? 0 : m_size - 1, m_data);
|
||||||
|
|
||||||
|
for (size_type i = m_size; i > index; --i, r1.sub(), r2.sub())
|
||||||
|
r1 = r2.get();
|
||||||
|
r1 = value;
|
||||||
|
m_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usu::vector<bool>::remove(size_type index) {
|
||||||
|
reference r1(index, m_data);
|
||||||
|
reference r2(index + 1 >= m_size ? index : index + 1, m_data);
|
||||||
|
|
||||||
|
for (size_type i = index; i < m_size; ++i, r1.add(), r2.add())
|
||||||
|
r1 = r2.get();
|
||||||
|
r1 = false;
|
||||||
|
m_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usu::vector<bool>::maybe_resize() {
|
||||||
|
if (m_data == nullptr)
|
||||||
|
m_data = std::make_shared<std::uint8_t[]>(m_capacity / 8);
|
||||||
|
if (m_size >= m_capacity) {
|
||||||
|
m_capacity = std::max(m_capacity == 0 ? 1 : m_resize(m_capacity), m_size);
|
||||||
|
|
||||||
|
pointer newData = std::make_shared<std::uint8_t[]>(m_capacity / 8);
|
||||||
|
for (size_type i = 0; i <= m_size / 8; ++i)
|
||||||
|
newData[i] = m_data[i];
|
||||||
|
|
||||||
|
m_data = newData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::iterator usu::vector<bool>::begin() {
|
||||||
|
vector<bool>::iterator begin(m_data);
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename usu::vector<bool>::iterator usu::vector<bool>::end() {
|
||||||
|
vector<bool>::iterator end(m_size, m_data);
|
||||||
|
return end;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user