#pragma once #include #include namespace std { template 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 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:: propagate_on_container_move_assignment::value || std::allocator_traits:: 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; } }; }