diff options
Diffstat (limited to 'euler/include/std/vector.hpp')
-rw-r--r-- | euler/include/std/vector.hpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/euler/include/std/vector.hpp b/euler/include/std/vector.hpp new file mode 100644 index 0000000..a1ac21d --- /dev/null +++ b/euler/include/std/vector.hpp @@ -0,0 +1,191 @@ +#pragma once + +#include <memory> + +namespace std { + + template <class T, class Allocator = std::allocator<T>> + class vector { + + public: + using size_type = size_t; + using value_type = T; + using reference = value_type &; + using const_reference = const value_type &; + + private: + Allocator _alloc; + size_type _capacity; + size_type _size; + T *_data; + + constexpr void expand_capacity_to(size_type at_least) { + + size_type new_capacity = _capacity == 0 ? 1 : _capacity; + while (new_capacity < at_least) + new_capacity *= 2; + if (new_capacity == _capacity) + return; + + T *new_data = _alloc.allocate(new_capacity); + for (size_type i = 0; i < _size; ++i) { + std::construct_at(new_data + i, std::move(_data[i])); + std::destroy_at(_data + i); + } + if (_capacity > 0) + _alloc.deallocate(_data, _capacity); + + _capacity = new_capacity; + _data = new_data; + + } + + public: + constexpr vector() noexcept(noexcept(Allocator())) + : _alloc(), _capacity(0), _size(0), _data(0) {} + + constexpr vector(const vector &other) + : _alloc(), _capacity(other._size), _size(other._size), + _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i, other._data[i]); + } + + constexpr vector(vector &&other) noexcept + : _alloc(std::move(other._alloc)), _capacity(other._capacity), + _size(other._size), _data(other._data) { + other._capacity = 0; + other._size = 0; + } + + constexpr vector( + std::initializer_list<T> init, const Allocator &alloc = Allocator()) + : _alloc(alloc), _capacity(init.size()), + _size(init.size()), _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i, init.begin()[i]); + } + + explicit vector(size_type count) + : _alloc(), _capacity(count), _size(count), + _data(_alloc.allocate(_capacity)) { + for (size_type i = 0; i < _size; ++i) + std::construct_at(_data + i); + } + + constexpr ~vector() { + if (_capacity > 0) { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _alloc.deallocate(_data, _capacity); + } + } + + constexpr vector &operator =(const vector &other) { + + if (&other == this) + return *this; + + expand_capacity_to(other._size); + + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + + for (size_type i = 0; i < other._size; ++i) { + std::construct_at(_data + i, std::move(other._data[i])); + std::destroy_at(other._data + i); + } + + _size = other._size; + return *this; + + } + + constexpr vector &operator =(vector &&other) + noexcept( + std::allocator_traits<Allocator>:: + propagate_on_container_move_assignment::value || + std::allocator_traits<Allocator>:: + is_always_equal::value) { + + if (&other == this) + return *this; + + if (_capacity > 0) { + for (size_type i = 0; i < _size; ++i) + std::destroy_at(_data + i); + _alloc.deallocate(_data, _capacity); + } + + _alloc = std::move(other._alloc); + _capacity = other._capacity; + _size = other._size; + _data = other._data; + + other._capacity = 0; + other._size = 0; + + return *this; + + } + + constexpr size_type size() const noexcept { + return _size; + } + + constexpr T *data() noexcept { + return _data; + } + + constexpr const T *data() const noexcept { + return _data; + } + + constexpr reference operator[](size_type pos) { + return _data[pos]; + } + + constexpr const_reference operator[](size_type pos) const { + return _data[pos]; + } + + constexpr reference back() { + return _data[_size - 1]; + } + + constexpr const_reference back() const { + return _data[_size - 1]; + } + + constexpr void resize(size_type count) { + + if (count < _size) { + for (size_type i = count; i < _size; ++i) + std::destroy_at(_data + i); + _size = count; + } + + else if (count > _size) { + expand_capacity_to(count); + for (size_type i = _size; i < count; ++i) + std::construct_at(_data + i); + _size = count; + } + + } + + constexpr void push_back(const T &value) { + expand_capacity_to(_size + 1); + std::construct_at(_data + _size, value); + ++_size; + } + + constexpr void push_back(T &&value) { + expand_capacity_to(_size + 1); + std::construct_at(_data + _size, std::move(value)); + ++_size; + } + + }; + +} |