Add initial vector implementation
This commit is contained in:
parent
f4e4ef353a
commit
b7683d45d5
284
include/mtl/vector.hpp
Normal file
284
include/mtl/vector.hpp
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <mtl/exception.hpp>
|
||||||
|
|
||||||
|
namespace mtl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Resizable statically allocated array
|
||||||
|
*
|
||||||
|
* Implements most functions from std::vector, see std::vector documentation
|
||||||
|
* for function descriptions. Some operations are unimplemented due to the lack
|
||||||
|
* of dynamic memory usage
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class ivector {
|
||||||
|
private:
|
||||||
|
T* m_arr;
|
||||||
|
size_t m_size;
|
||||||
|
const size_t m_capacity;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using size_type = size_t;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using iterator = T*;
|
||||||
|
using const_iterator = const T*;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
ivector(T* arr, size_t capacity) : m_arr(arr), m_capacity(capacity), m_size(0) {}
|
||||||
|
/**
|
||||||
|
* \brief Copy constructor
|
||||||
|
*
|
||||||
|
* \exception mtl::length_error Thrown if the source vector's size is
|
||||||
|
* larger than the new capacity
|
||||||
|
*/
|
||||||
|
ivector(T* arr, size_t capacity, const ivector& other) : m_arr(arr), m_capacity(capacity) {
|
||||||
|
if (&other == this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other.m_size > m_capacity) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
T* x = m_arr;
|
||||||
|
T* begin = other.m_arr;
|
||||||
|
T* end = other.m_arr + other.m_size;
|
||||||
|
for (; begin != end; ++x, ++begin) {
|
||||||
|
*x = *begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_size = other.m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Move constructor
|
||||||
|
*
|
||||||
|
* \exception mtl::length_error Thrown if the source vector's size is
|
||||||
|
* larger than the new capacity
|
||||||
|
*/
|
||||||
|
ivector(ivector&& other) {
|
||||||
|
if (&other == this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (other.m_size > m_capacity) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're not able to simply swap pointers because dynamic memory
|
||||||
|
// is not used. However, we can still swap each individual
|
||||||
|
// element if possible.
|
||||||
|
T* x = m_arr;
|
||||||
|
T* begin = other.m_arr;
|
||||||
|
T* end = other.m_arr + other.m_size;
|
||||||
|
for (; begin != end; ++x, ++begin) {
|
||||||
|
*x = std::move(*begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_size = other.m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ivector() {}
|
||||||
|
|
||||||
|
ivector& operator=(ivector rhs) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(size_t count, const T& value) {
|
||||||
|
throw mtl::system_error();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* \brief Assigns values to the vector
|
||||||
|
*
|
||||||
|
* \exception mtl::length_error Thrown if the number of source elements
|
||||||
|
* is larger than the capacity
|
||||||
|
*/
|
||||||
|
template <typename It>
|
||||||
|
void assign(It begin, It end) {
|
||||||
|
m_size = 0;
|
||||||
|
T* x = m_arr;
|
||||||
|
|
||||||
|
for (; begin != end; ++begin, ++x, ++m_size) {
|
||||||
|
if (m_size > m_capacity) {
|
||||||
|
//throw mtl::length_error();
|
||||||
|
}
|
||||||
|
*x = *begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Bounds-checked element access
|
||||||
|
*
|
||||||
|
* \exception mtl::out_of_range Thrown if pos > size
|
||||||
|
*/
|
||||||
|
reference at(size_t pos) {
|
||||||
|
if (pos > m_size) {
|
||||||
|
throw mtl::out_of_range();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_arr[pos];
|
||||||
|
}
|
||||||
|
const_reference at(size_t pos) const {
|
||||||
|
if (pos > m_size) {
|
||||||
|
throw mtl::out_of_range();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_arr[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator[](size_t pos) {
|
||||||
|
return m_arr[pos];
|
||||||
|
}
|
||||||
|
const_reference operator[](size_t pos) const {
|
||||||
|
return m_arr[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
reference front() {
|
||||||
|
return m_arr[0];
|
||||||
|
}
|
||||||
|
const_reference front() const {
|
||||||
|
return m_arr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
reference back() {
|
||||||
|
return m_arr[m_size - 1];
|
||||||
|
}
|
||||||
|
const_reference back() const {
|
||||||
|
return m_arr[m_size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer data() {
|
||||||
|
return m_arr;
|
||||||
|
}
|
||||||
|
const_pointer data() const {
|
||||||
|
return m_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return m_arr;
|
||||||
|
}
|
||||||
|
const_iterator begin() const {
|
||||||
|
return m_arr;
|
||||||
|
}
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return m_arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return m_arr + m_size;
|
||||||
|
}
|
||||||
|
const_iterator end() const {
|
||||||
|
return m_arr + m_size;
|
||||||
|
}
|
||||||
|
const_iterator cend() const {
|
||||||
|
return m_arr + m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_iterator rbegin() {
|
||||||
|
return reverse_iterator(end());
|
||||||
|
}
|
||||||
|
const_reverse_iterator rbegin() const {
|
||||||
|
return const_reverse_iterator(cend());
|
||||||
|
}
|
||||||
|
const_reverse_iterator crbegin() const {
|
||||||
|
return const_reverse_iterator(cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_iterator rend() {
|
||||||
|
return reverse_iterator(begin());
|
||||||
|
}
|
||||||
|
const_reverse_iterator rend() const {
|
||||||
|
return const_reverse_iterator(cbegin());
|
||||||
|
}
|
||||||
|
const_reverse_iterator crend() const {
|
||||||
|
return const_reverse_iterator(cbegin());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return m_size == 0;
|
||||||
|
}
|
||||||
|
size_t size() const {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
size_t capacity() const {
|
||||||
|
return m_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator insert(const_iterator pos, T value) {
|
||||||
|
if (m_size == m_capacity) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator it = end();
|
||||||
|
while (it != pos) {
|
||||||
|
*it = *(it - 1);
|
||||||
|
--it;
|
||||||
|
}
|
||||||
|
|
||||||
|
*it = std::move(value);
|
||||||
|
++m_size;
|
||||||
|
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Erase the element at the given iterator
|
||||||
|
*
|
||||||
|
* \param pos iterator of the element to erase
|
||||||
|
* \exception nothrow if `T` is nothrow assignable
|
||||||
|
* \returns iterator of the element after element erased
|
||||||
|
*/
|
||||||
|
iterator erase(const_iterator pos) noexcept(std::is_nothrow_assignable<T, T>::value) {
|
||||||
|
iterator it = const_cast<iterator>(pos);
|
||||||
|
iterator last = end() - 1;
|
||||||
|
|
||||||
|
while (it != last) {
|
||||||
|
*it = *(it + 1);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
--m_size;
|
||||||
|
|
||||||
|
return const_cast<iterator>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(T value) {
|
||||||
|
if (m_size == m_capacity) {
|
||||||
|
throw mtl::length_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_arr[m_size] = std::move(value);
|
||||||
|
++m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back() noexcept {
|
||||||
|
if (m_size > 0) {
|
||||||
|
--m_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, size_t C>
|
||||||
|
class vector : public ivector<T> {
|
||||||
|
private:
|
||||||
|
T m_arr[C];
|
||||||
|
|
||||||
|
public:
|
||||||
|
vector() : ivector<T>(m_arr, C) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mtl
|
||||||
Loading…
x
Reference in New Issue
Block a user