#pragma once #if !defined(BAD_APPLE_OS_VECTOR_INCLUDED) #define BAD_APPLE_OS_VECTOR_INCLUDED #include #include #include #include namespace std { template // TODO: allocator class vector { public: 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 = pointer; using const_iterator = const_pointer; private: T* _elements = nullptr; size_type _size = 0; size_type _capacity = 0; public: constexpr vector() noexcept = default; constexpr vector(const vector& other) noexcept { resize(other.size()); for (size_type idx = 0; idx < size(); ++idx) { (*this)[idx] = other[idx]; } } constexpr vector(vector&& other) noexcept : _elements(exchange(other._elements, nullptr)), _size(exchange(other._size, 0)), _capacity(exchange(other._capacity, 0)) { } constexpr explicit vector(size_type count, const value_type& value = value_type()) { resize(count, value); } constexpr ~vector() noexcept { delete _elements; } constexpr vector& operator=(const vector& other) { if (this == &other) { return *this; } resize(other.size()); for (size_type idx = 0; idx < size(); ++idx) { (*this)[idx] = other[idx]; } return *this; } constexpr vector& operator=(vector&& other) { if (this == &other) { return *this; } clear(); _elements = exchange(other._elements, nullptr); _size = exchange(other._size, 0); _capacity = exchange(other._capacity, 0); return *this; } [[nodiscard]] constexpr reference operator[](size_type pos) noexcept { return _elements[pos]; } [[nodiscard]] constexpr const_reference operator[](size_type pos) const noexcept { return _elements[pos]; } [[nodiscard]] constexpr reference at(size_type pos) { if (pos >= size()) { __ba_throw out_of_range(); } return _elements[pos]; } [[nodiscard]] constexpr const_reference at(size_type pos) const { if (pos >= size()) { __ba_throw out_of_range(); } return _elements[pos]; } [[nodiscard]] constexpr reference front() noexcept { return _elements[0]; } [[nodiscard]] constexpr const_reference front() const noexcept { return _elements[0]; } [[nodiscard]] constexpr reference back() noexcept { return _elements[size() - 1]; } [[nodiscard]] constexpr const_reference back() const noexcept { return _elements[size() - 1]; } [[nodiscard]] constexpr pointer data() noexcept { return _elements; } [[nodiscard]] constexpr const_pointer data() const noexcept { return _elements; } [[nodiscard]] constexpr iterator begin() noexcept { return _elements; } [[nodiscard]] constexpr const_iterator begin() const noexcept { return _elements; } [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return _elements; } [[nodiscard]] constexpr iterator end() noexcept { return &_elements[size()]; } [[nodiscard]] constexpr const_iterator end() const noexcept { return &_elements[size()]; } [[nodiscard]] constexpr const_iterator cend() const noexcept { return &_elements[size()]; } [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } [[nodiscard]] constexpr size_type size() const noexcept { return _size; } [[nodiscard]] constexpr size_type max_size() const noexcept { return size_type(-1); } constexpr void reserve(size_type newCapacity) { if (newCapacity <= capacity()) { return; } updateCapacity(newCapacity); } [[nodiscard]] size_type capacity() const noexcept { return _capacity; } constexpr void shrink_to_fit() { updateCapacity(size()); } constexpr void clear() { resize(0); } constexpr void push_back(const value_type& value) { reserve(size() + 1); ::new (&_elements[size()]) T(value); ++_size; } constexpr void push_back(value_type&& value) { reserve(size() + 1); ::new (&_elements[size()]) T(std::move(value)); ++_size; } constexpr void pop_back() noexcept { resize(size() - 1); } template constexpr reference emplace_back(TArgs&&... args) { reserve(size() + 1); ::new (&_elements[size()]) T(std::forward(args)...); ++_size; } constexpr void resize(size_type newSize) { if (newSize == size()) { return; } reserve(newSize); if (newSize > size()) { for (size_type idx = size(); idx < newSize; ++idx) { ::new (&_elements[idx]) T(); } } else { for (size_type idx = newSize; idx < size(); ++idx) { _elements[idx].~T(); } } _size = newSize; } constexpr void resize(size_type newSize, const value_type& initValue) { if (newSize == size()) { return; } reserve(newSize); if (newSize > size()) { for (size_type idx = size(); idx < newSize; ++idx) { ::new (&_elements[idx]) T(initValue); } } else { for (size_type idx = newSize; idx < size(); ++idx) { _elements[idx].~T(); } } _size = newSize; } private: void updateCapacity(size_type newCapacity) { if (capacity() == newCapacity) { return; } T* newElements = static_cast(malloc(newCapacity * sizeof(T))); for (size_type idx = 0; idx < size(); ++idx) { ::new (&newElements[idx]) T(move(_elements[idx])); _elements[idx].~T(); } free(_elements); _elements = newElements; _capacity = newCapacity; } }; } #endif // !defined(BAD_APPLE_OS_VECTOR_INCLUDED)