mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-25 22:14:34 +00:00
1040 lines
25 KiB
Plaintext
1040 lines
25 KiB
Plaintext
/*
|
|
This file is part of Fennix Kernel.
|
|
|
|
Fennix Kernel is free software: you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation, either version 3 of
|
|
the License, or (at your option) any later version.
|
|
|
|
Fennix Kernel is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <initializer_list>
|
|
#include <stdexcept>
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <compare>
|
|
#include <memory>
|
|
|
|
namespace std
|
|
{
|
|
template <class T, class Allocator = std::allocator<T>>
|
|
class vector
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using allocator_type = Allocator;
|
|
using size_type = std::size_t;
|
|
using difference_type = std::ptrdiff_t;
|
|
using reference = value_type &;
|
|
using const_reference = const value_type &;
|
|
using pointer = typename std::allocator_traits<Allocator>::pointer;
|
|
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
|
|
// using iterator = typename vector<T, Allocator>::iterator;
|
|
// using const_iterator = typename vector<T, Allocator>::const_iterator;
|
|
// using reverse_iterator = typename vector<T, Allocator>::reverse_iterator;
|
|
// using const_reverse_iterator = typename vector<T, Allocator>::const_reverse_iterator;
|
|
|
|
class iterator
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = T *;
|
|
using reference = T &;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
public:
|
|
pointer itrPtr;
|
|
|
|
public:
|
|
constexpr iterator() noexcept : itrPtr(nullptr) {}
|
|
constexpr iterator(pointer ptr) noexcept : itrPtr(ptr) {}
|
|
constexpr iterator(const iterator &other) noexcept : itrPtr(other.itrPtr) {}
|
|
constexpr iterator(iterator &&other) noexcept : itrPtr(other.itrPtr) {}
|
|
|
|
constexpr reference operator*() const { return *itrPtr; }
|
|
constexpr pointer operator->() const { return itrPtr; }
|
|
|
|
constexpr iterator &operator=(const iterator &other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr iterator &operator=(iterator &&other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr iterator &operator++()
|
|
{
|
|
itrPtr++;
|
|
return *this;
|
|
}
|
|
|
|
constexpr iterator operator++(int)
|
|
{
|
|
iterator temp = *this;
|
|
itrPtr++;
|
|
return temp;
|
|
}
|
|
|
|
constexpr iterator &operator--()
|
|
{
|
|
itrPtr--;
|
|
return *this;
|
|
}
|
|
|
|
constexpr iterator operator--(int)
|
|
{
|
|
iterator temp = *this;
|
|
itrPtr--;
|
|
return temp;
|
|
}
|
|
|
|
constexpr difference_type operator-(const iterator &other) const
|
|
{
|
|
return itrPtr - other.itrPtr;
|
|
}
|
|
|
|
constexpr iterator operator+(difference_type n) const
|
|
{
|
|
return iterator(itrPtr + n);
|
|
}
|
|
|
|
constexpr bool operator==(const iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const iterator &other) const { return itrPtr != other.itrPtr; }
|
|
};
|
|
|
|
class const_iterator
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = const T *;
|
|
using reference = const T &;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
public:
|
|
pointer itrPtr;
|
|
|
|
public:
|
|
constexpr const_iterator() noexcept : itrPtr(nullptr) {}
|
|
constexpr const_iterator(pointer ptr) noexcept : itrPtr(ptr) {}
|
|
constexpr const_iterator(iterator it) noexcept : itrPtr(it.itrPtr) {}
|
|
constexpr const_iterator(const const_iterator &other) noexcept : itrPtr(other.itrPtr) {}
|
|
constexpr const_iterator(const_iterator &&other) noexcept : itrPtr(other.itrPtr) {}
|
|
|
|
constexpr reference operator*() const { return *itrPtr; }
|
|
constexpr pointer operator->() const { return itrPtr; }
|
|
|
|
constexpr const_iterator &operator=(const const_iterator &other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_iterator &operator=(const_iterator &&other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_iterator &operator++()
|
|
{
|
|
itrPtr++;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_iterator operator++(int)
|
|
{
|
|
const_iterator temp = *this;
|
|
itrPtr++;
|
|
return temp;
|
|
}
|
|
|
|
constexpr const_iterator &operator--()
|
|
{
|
|
itrPtr--;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_iterator operator--(int)
|
|
{
|
|
const_iterator temp = *this;
|
|
itrPtr--;
|
|
return temp;
|
|
}
|
|
|
|
constexpr difference_type operator-(const const_iterator &other) const
|
|
{
|
|
return itrPtr - other.itrPtr;
|
|
}
|
|
|
|
constexpr const_iterator operator+(difference_type n) const
|
|
{
|
|
return const_iterator(itrPtr + n);
|
|
}
|
|
|
|
constexpr bool operator==(const const_iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const const_iterator &other) const { return itrPtr != other.itrPtr; }
|
|
};
|
|
|
|
class reverse_iterator
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = T *;
|
|
using reference = T &;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
public:
|
|
pointer itrPtr;
|
|
|
|
public:
|
|
constexpr reverse_iterator() noexcept : itrPtr(nullptr) {}
|
|
constexpr reverse_iterator(pointer ptr) noexcept : itrPtr(ptr) {}
|
|
constexpr reverse_iterator(const reverse_iterator &other) noexcept : itrPtr(other.itrPtr) {}
|
|
constexpr reverse_iterator(reverse_iterator &&other) noexcept : itrPtr(other.itrPtr) {}
|
|
|
|
constexpr reference operator*() const { return *itrPtr; }
|
|
constexpr pointer operator->() const { return itrPtr; }
|
|
|
|
constexpr reverse_iterator &operator=(const reverse_iterator &other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr reverse_iterator &operator=(reverse_iterator &&other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr reverse_iterator &operator++()
|
|
{
|
|
itrPtr--;
|
|
return *this;
|
|
}
|
|
|
|
constexpr reverse_iterator operator++(int)
|
|
{
|
|
reverse_iterator temp = *this;
|
|
itrPtr--;
|
|
return temp;
|
|
}
|
|
|
|
constexpr reverse_iterator &operator--()
|
|
{
|
|
itrPtr++;
|
|
return *this;
|
|
}
|
|
|
|
constexpr reverse_iterator operator--(int)
|
|
{
|
|
reverse_iterator temp = *this;
|
|
itrPtr++;
|
|
return temp;
|
|
}
|
|
|
|
constexpr difference_type operator-(const reverse_iterator &other) const
|
|
{
|
|
return itrPtr - other.itrPtr;
|
|
}
|
|
|
|
constexpr reverse_iterator operator+(difference_type n) const
|
|
{
|
|
return reverse_iterator(itrPtr - n);
|
|
}
|
|
|
|
constexpr bool operator==(const reverse_iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const reverse_iterator &other) const { return itrPtr != other.itrPtr; }
|
|
|
|
constexpr bool operator==(const const_iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const const_iterator &other) const { return itrPtr != other.itrPtr; }
|
|
|
|
constexpr bool operator==(const iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const iterator &other) const { return itrPtr != other.itrPtr; }
|
|
};
|
|
|
|
class const_reverse_iterator
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = const T *;
|
|
using reference = const T &;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
public:
|
|
pointer itrPtr;
|
|
|
|
public:
|
|
constexpr const_reverse_iterator() noexcept : itrPtr(nullptr) {}
|
|
constexpr const_reverse_iterator(pointer ptr) noexcept : itrPtr(ptr) {}
|
|
constexpr const_reverse_iterator(const const_reverse_iterator &other) noexcept : itrPtr(other.itrPtr) {}
|
|
constexpr const_reverse_iterator(const_reverse_iterator &&other) noexcept : itrPtr(other.itrPtr) {}
|
|
|
|
constexpr reference operator*() const { return *itrPtr; }
|
|
constexpr pointer operator->() const { return itrPtr; }
|
|
|
|
constexpr const_reverse_iterator &operator=(const const_reverse_iterator &other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_reverse_iterator &operator=(const_reverse_iterator &&other)
|
|
{
|
|
itrPtr = other.itrPtr;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_reverse_iterator &operator++()
|
|
{
|
|
itrPtr--;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_reverse_iterator operator++(int)
|
|
{
|
|
const_reverse_iterator temp = *this;
|
|
itrPtr--;
|
|
return temp;
|
|
}
|
|
|
|
constexpr const_reverse_iterator &operator--()
|
|
{
|
|
itrPtr++;
|
|
return *this;
|
|
}
|
|
|
|
constexpr const_reverse_iterator operator--(int)
|
|
{
|
|
const_reverse_iterator temp = *this;
|
|
itrPtr++;
|
|
return temp;
|
|
}
|
|
|
|
constexpr difference_type operator-(const const_reverse_iterator &other) const
|
|
{
|
|
return itrPtr - other.itrPtr;
|
|
}
|
|
|
|
constexpr const_reverse_iterator operator+(difference_type n) const
|
|
{
|
|
return const_reverse_iterator(itrPtr - n);
|
|
}
|
|
|
|
constexpr bool operator==(const const_reverse_iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const const_reverse_iterator &other) const { return itrPtr != other.itrPtr; }
|
|
|
|
constexpr bool operator==(const reverse_iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const reverse_iterator &other) const { return itrPtr != other.itrPtr; }
|
|
|
|
constexpr bool operator==(const const_iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const const_iterator &other) const { return itrPtr != other.itrPtr; }
|
|
|
|
constexpr bool operator==(const iterator &other) const { return itrPtr == other.itrPtr; }
|
|
constexpr bool operator!=(const iterator &other) const { return itrPtr != other.itrPtr; }
|
|
};
|
|
|
|
private:
|
|
allocator_type _alloc;
|
|
size_type _size;
|
|
size_type _capacity;
|
|
pointer _data;
|
|
|
|
public:
|
|
#pragma region Constructors
|
|
|
|
constexpr vector() noexcept(noexcept(Allocator()))
|
|
: _size(0),
|
|
_capacity(0),
|
|
_data(nullptr)
|
|
{
|
|
}
|
|
|
|
constexpr explicit vector(const Allocator &alloc) noexcept
|
|
: _alloc(alloc),
|
|
_size(0),
|
|
_capacity(0),
|
|
_data(nullptr)
|
|
{
|
|
}
|
|
|
|
constexpr vector(size_type count, const T &value, const Allocator &alloc = Allocator())
|
|
: _alloc(alloc),
|
|
_size(count),
|
|
_capacity(count),
|
|
_data(_alloc.allocate(count))
|
|
{
|
|
for (size_type i = 0; i < count; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, value);
|
|
}
|
|
|
|
constexpr explicit vector(size_type count, const Allocator &alloc = Allocator())
|
|
: _alloc(alloc),
|
|
_size(count),
|
|
_capacity(count),
|
|
_data(_alloc.allocate(count))
|
|
{
|
|
for (size_type i = 0; i < count; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i);
|
|
}
|
|
|
|
/* FIXME: this conflicts with the above constructors */
|
|
// template <class InputIt>
|
|
// constexpr vector(InputIt first, InputIt last, const Allocator &alloc = Allocator())
|
|
// {
|
|
// _alloc = alloc;
|
|
// _size = last - first;
|
|
// _capacity = last - first;
|
|
// _data = _alloc.allocate(_size);
|
|
// for (size_type i = 0; i < _size; i++)
|
|
// std::allocator_traits<Allocator>::construct(_alloc, _data + i, *(first + i));
|
|
// }
|
|
|
|
constexpr vector(const vector &other)
|
|
: _alloc(other._alloc),
|
|
_size(other._size),
|
|
_capacity(other._capacity),
|
|
_data(_alloc.allocate(_size))
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, other._data[i]);
|
|
}
|
|
|
|
constexpr vector(const vector &other, const Allocator &alloc)
|
|
: _alloc(other._alloc),
|
|
_size(other._size),
|
|
_capacity(other._capacity),
|
|
_data(_alloc.allocate(_size))
|
|
{
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, other._data[i]);
|
|
}
|
|
|
|
constexpr vector(vector &&other) noexcept
|
|
: _alloc(std::move(other._alloc)),
|
|
_size(other._size),
|
|
_capacity(other._capacity),
|
|
_data(other._data)
|
|
{
|
|
other._size = 0;
|
|
other._capacity = 0;
|
|
other._data = nullptr;
|
|
}
|
|
|
|
constexpr vector(vector &&other, const Allocator &alloc)
|
|
: _alloc(alloc),
|
|
_size(other._size),
|
|
_capacity(other._capacity),
|
|
_data(other._data)
|
|
{
|
|
other._size = 0;
|
|
other._capacity = 0;
|
|
other._data = nullptr;
|
|
}
|
|
|
|
constexpr vector(std::initializer_list<T> init, const Allocator &alloc = Allocator())
|
|
: _alloc(alloc),
|
|
_size(init.size()),
|
|
_capacity(init.size()),
|
|
_data(_alloc.allocate(_size))
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, *(init.begin() + i));
|
|
}
|
|
|
|
constexpr ~vector()
|
|
{
|
|
if (_capacity == 0 || _data == nullptr)
|
|
return;
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
_alloc.deallocate(_data, _size);
|
|
}
|
|
|
|
constexpr vector &operator=(const vector &other)
|
|
{
|
|
if (this == &other)
|
|
return *this;
|
|
|
|
if (_capacity != 0 && _data != nullptr)
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
_alloc.deallocate(_data, _size);
|
|
}
|
|
|
|
_size = other._size;
|
|
_capacity = other._capacity;
|
|
_data = _alloc.allocate(_size);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, other._data[i]);
|
|
|
|
return *this;
|
|
}
|
|
|
|
constexpr vector &operator=(vector &&other) /* noexcept(_alloc.propagate_on_container_move_assignment::value || _alloc.is_always_equal::value) */
|
|
{
|
|
if (this == &other)
|
|
return *this;
|
|
|
|
if (_capacity != 0 && _data != nullptr)
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
_alloc.deallocate(_data, _size);
|
|
}
|
|
|
|
_size = other._size;
|
|
_capacity = other._capacity;
|
|
_data = other._data;
|
|
other._size = 0;
|
|
other._capacity = 0;
|
|
other._data = nullptr;
|
|
|
|
return *this;
|
|
}
|
|
|
|
constexpr vector &operator=(std::initializer_list<T> ilist)
|
|
{
|
|
_size = ilist.size();
|
|
_capacity = ilist.size();
|
|
_data = _alloc.allocate(_size);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, *(ilist.begin() + i));
|
|
|
|
return *this;
|
|
}
|
|
|
|
constexpr void assign(size_type count, const T &value)
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
if (_data != nullptr)
|
|
_alloc.deallocate(_data, _size);
|
|
|
|
_size = count;
|
|
_capacity = count;
|
|
_data = _alloc.allocate(_size);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, value);
|
|
}
|
|
|
|
template <class InputIt>
|
|
constexpr void assign(InputIt first, InputIt last)
|
|
{
|
|
if (_capacity != 0 && _data != nullptr)
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
_alloc.deallocate(_data, _size);
|
|
}
|
|
|
|
_size = last - first;
|
|
_capacity = last - first;
|
|
_data = _alloc.allocate(_size);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, *(first + i));
|
|
}
|
|
|
|
constexpr void assign(std::initializer_list<T> ilist)
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
if (_data != nullptr)
|
|
_alloc.deallocate(_data, _size);
|
|
|
|
_size = ilist.size();
|
|
_capacity = ilist.size();
|
|
_data = _alloc.allocate(_size);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, *(ilist.begin() + i));
|
|
}
|
|
|
|
constexpr allocator_type get_allocator() const noexcept
|
|
{
|
|
return _alloc;
|
|
}
|
|
|
|
#pragma endregion Constructors
|
|
|
|
#pragma region Element Access
|
|
|
|
reference at(size_type pos)
|
|
{
|
|
if (pos >= _size)
|
|
throw std::out_of_range("vector::at");
|
|
|
|
return _data[pos];
|
|
}
|
|
|
|
const_reference at(size_type pos) const
|
|
{
|
|
if (pos >= _size)
|
|
throw std::out_of_range("vector::at");
|
|
|
|
return _data[pos];
|
|
}
|
|
|
|
reference operator[](size_type pos)
|
|
{
|
|
return _data[pos];
|
|
}
|
|
|
|
const_reference operator[](size_type pos) const
|
|
{
|
|
return _data[pos];
|
|
}
|
|
|
|
reference front()
|
|
{
|
|
return _data[0];
|
|
}
|
|
|
|
const_reference front() const
|
|
{
|
|
return _data[0];
|
|
}
|
|
|
|
reference back()
|
|
{
|
|
return _data[_size - 1];
|
|
}
|
|
|
|
const_reference back() const
|
|
{
|
|
return _data[_size - 1];
|
|
}
|
|
|
|
constexpr T *data() noexcept
|
|
{
|
|
return _data;
|
|
}
|
|
|
|
constexpr const T *data() const
|
|
{
|
|
return _data;
|
|
}
|
|
|
|
#pragma endregion Element Access
|
|
|
|
#pragma region Iterators
|
|
|
|
constexpr iterator begin()
|
|
{
|
|
return iterator(_data);
|
|
}
|
|
|
|
constexpr const_iterator begin() const
|
|
{
|
|
return const_iterator(_data);
|
|
}
|
|
|
|
constexpr const_iterator cbegin() const noexcept
|
|
{
|
|
return const_iterator(_data);
|
|
}
|
|
|
|
constexpr iterator end() noexcept
|
|
{
|
|
return iterator(_data + _size);
|
|
}
|
|
|
|
constexpr const_iterator end() const noexcept
|
|
{
|
|
return const_iterator(_data + _size);
|
|
}
|
|
|
|
constexpr const_iterator cend() const noexcept
|
|
{
|
|
return const_iterator(_data + _size);
|
|
}
|
|
|
|
constexpr reverse_iterator rbegin()
|
|
{
|
|
return reverse_iterator(_data + _size - 1);
|
|
}
|
|
|
|
constexpr const_reverse_iterator rbegin() const
|
|
{
|
|
return const_reverse_iterator(_data + _size - 1);
|
|
}
|
|
|
|
constexpr const_reverse_iterator crbegin() const noexcept
|
|
{
|
|
return const_reverse_iterator(_data + _size - 1);
|
|
}
|
|
|
|
constexpr iterator rend() noexcept
|
|
{
|
|
return iterator(_data - 1);
|
|
}
|
|
|
|
constexpr const_iterator rend() const noexcept
|
|
{
|
|
return const_iterator(_data - 1);
|
|
}
|
|
|
|
constexpr const_iterator crend() const noexcept
|
|
{
|
|
return const_iterator(_data - 1);
|
|
}
|
|
|
|
#pragma endregion Iterators
|
|
|
|
#pragma region Capacity
|
|
|
|
[[nodiscard]] constexpr bool empty() const noexcept
|
|
{
|
|
return _size == 0; /* begin() == end() */
|
|
}
|
|
|
|
constexpr size_type size() const noexcept
|
|
{
|
|
return _size; /* std::distance(begin(), end()) */
|
|
}
|
|
|
|
constexpr size_type max_size() const noexcept
|
|
{
|
|
return std::numeric_limits<difference_type>::max();
|
|
}
|
|
|
|
constexpr void reserve(size_type new_cap)
|
|
{
|
|
if (new_cap <= _capacity)
|
|
return;
|
|
|
|
pointer new_data = _alloc.allocate(new_cap);
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, new_data + i, _data[i]);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
if (_data != nullptr)
|
|
_alloc.deallocate(_data, _size);
|
|
|
|
_data = new_data;
|
|
_capacity = new_cap;
|
|
}
|
|
|
|
constexpr size_type capacity() const noexcept
|
|
{
|
|
return _capacity;
|
|
}
|
|
|
|
constexpr void shrink_to_fit()
|
|
{
|
|
if (_size >= _capacity)
|
|
return;
|
|
|
|
pointer new_data = _alloc.allocate(_size);
|
|
for (size_type i = 0; i < _size; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, new_data + i, _data[i]);
|
|
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
if (_data != nullptr)
|
|
_alloc.deallocate(_data, _size);
|
|
_data = new_data;
|
|
_capacity = _size;
|
|
}
|
|
|
|
#pragma endregion Capacity
|
|
|
|
#pragma region Modifiers
|
|
|
|
constexpr void clear() noexcept
|
|
{
|
|
for (size_type i = 0; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
_size = 0;
|
|
}
|
|
|
|
constexpr iterator insert(const_iterator pos, const T &value)
|
|
{
|
|
size_type index = pos - begin();
|
|
if (_size == _capacity)
|
|
reserve(_capacity + (_capacity / 2) + 1);
|
|
|
|
for (size_type i = _size; i > index; i--)
|
|
_data[i] = _data[i - 1];
|
|
|
|
_data[index] = value;
|
|
_size++;
|
|
return iterator(_data + index);
|
|
}
|
|
|
|
constexpr iterator insert(const_iterator pos, size_type count, const T &value)
|
|
{
|
|
size_type index = pos - begin();
|
|
if (_size + count > _capacity)
|
|
reserve(_capacity + count);
|
|
|
|
for (size_type i = _size + count - 1; i > index + count - 1; i--)
|
|
_data[i] = _data[i - count];
|
|
|
|
for (size_type i = index; i < index + count; i++)
|
|
_data[i] = value;
|
|
|
|
_size += count;
|
|
return iterator(_data + index);
|
|
}
|
|
template <class InputIt>
|
|
constexpr iterator insert(const_iterator pos, InputIt first, InputIt last)
|
|
{
|
|
size_type index = pos - begin();
|
|
size_type count = last - first;
|
|
if (_size + count > _capacity)
|
|
reserve(_capacity + count);
|
|
|
|
for (size_type i = _size + count - 1; i > index + count - 1; i--)
|
|
_data[i] = _data[i - count];
|
|
|
|
for (size_type i = index; i < index + count; i++)
|
|
_data[i] = *(first + i - index);
|
|
|
|
_size += count;
|
|
return iterator(_data + index);
|
|
}
|
|
|
|
constexpr iterator insert(const_iterator pos,
|
|
std::initializer_list<T> ilist)
|
|
{
|
|
size_type index = pos - begin();
|
|
size_type count = ilist.size();
|
|
if (_size + count > _capacity)
|
|
reserve(_capacity + count);
|
|
|
|
for (size_type i = _size + count - 1; i > index + count - 1; i--)
|
|
_data[i] = _data[i - count];
|
|
|
|
for (size_type i = index; i < index + count; i++)
|
|
_data[i] = *(ilist.begin() + i - index);
|
|
|
|
_size += count;
|
|
return iterator(_data + index);
|
|
}
|
|
|
|
template <class... Args>
|
|
constexpr iterator emplace(const_iterator pos, Args &&...args)
|
|
{
|
|
size_type index = pos - begin();
|
|
if (_size == _capacity)
|
|
reserve(_capacity + (_capacity / 2) + 1);
|
|
|
|
for (size_type i = _size; i > index; i--)
|
|
_data[i] = _data[i - 1];
|
|
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + index, std::forward<Args>(args)...);
|
|
_size++;
|
|
return iterator(_data + index);
|
|
}
|
|
|
|
constexpr iterator erase(const_iterator pos)
|
|
{
|
|
size_type index = pos - cbegin();
|
|
for (size_type i = index; i < _size - 1; i++)
|
|
_data[i] = _data[i + 1];
|
|
|
|
_data[_size - 1].~value_type();
|
|
_size--;
|
|
return iterator(_data + index);
|
|
}
|
|
|
|
constexpr iterator erase(const_iterator first, const_iterator last)
|
|
{
|
|
size_type index = first - cbegin();
|
|
size_type count = last - first;
|
|
for (size_type i = index; i < _size - count; i++)
|
|
_data[i] = _data[i + count];
|
|
|
|
for (size_type i = _size - count; i < _size; i++)
|
|
_data[i].~value_type();
|
|
|
|
_size -= count;
|
|
return iterator(_data + index);
|
|
}
|
|
|
|
constexpr void push_back(const T &value)
|
|
{
|
|
if (_capacity == 0)
|
|
reserve(sizeof(T) * 2);
|
|
|
|
if (_size == _capacity)
|
|
reserve(_capacity + (_capacity / 2) + 1);
|
|
|
|
_data[_size] = value;
|
|
_size++;
|
|
}
|
|
|
|
constexpr void push_back(T &&value)
|
|
{
|
|
if (_capacity == 0)
|
|
reserve(sizeof(T) * 2);
|
|
|
|
if (_size == _capacity)
|
|
reserve(_capacity + (_capacity / 2) + 1);
|
|
|
|
_data[_size] = std::move(value);
|
|
_size++;
|
|
}
|
|
|
|
template <class... Args>
|
|
constexpr reference emplace_back(Args &&...args)
|
|
{
|
|
if (_size == _capacity)
|
|
reserve(_capacity + (_capacity / 2) + 1);
|
|
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + _size, std::forward<Args>(args)...);
|
|
_size++;
|
|
return _data[_size - 1];
|
|
}
|
|
|
|
constexpr void pop_back()
|
|
{
|
|
_data[_size - 1].~value_type();
|
|
_size--;
|
|
}
|
|
|
|
constexpr void resize(size_type count)
|
|
{
|
|
if (count > _size)
|
|
{
|
|
if (count > _capacity)
|
|
reserve(count);
|
|
|
|
for (size_type i = _size; i < count; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i);
|
|
}
|
|
else
|
|
{
|
|
for (size_type i = count; i < _size; i++)
|
|
_data[i].~value_type();
|
|
}
|
|
_size = count;
|
|
}
|
|
|
|
constexpr void resize(size_type count, const value_type &value)
|
|
{
|
|
if (count > _size)
|
|
{
|
|
if (count > _capacity)
|
|
reserve(count);
|
|
|
|
for (size_type i = _size; i < count; i++)
|
|
std::allocator_traits<Allocator>::construct(_alloc, _data + i, value);
|
|
}
|
|
else
|
|
{
|
|
for (size_type i = count; i < _size; i++)
|
|
_data[i].~value_type();
|
|
}
|
|
_size = count;
|
|
}
|
|
|
|
constexpr void swap(vector &other) /* noexcept(_alloc.propagate_on_container_swap::value || _alloc.is_always_equal::value) */
|
|
{
|
|
size_type temp_size = _size;
|
|
size_type temp_capacity = _capacity;
|
|
pointer temp_data = _data;
|
|
|
|
_size = other._size;
|
|
_capacity = other._capacity;
|
|
_data = other._data;
|
|
|
|
other._size = temp_size;
|
|
other._capacity = temp_capacity;
|
|
other._data = temp_data;
|
|
}
|
|
|
|
#pragma endregion Modifiers
|
|
};
|
|
|
|
template <class T, class Alloc>
|
|
constexpr bool operator==(const std::vector<T, Alloc> &lhs, const std::vector<T, Alloc> &rhs)
|
|
{
|
|
if (lhs.size() != rhs.size())
|
|
return false;
|
|
|
|
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
|
}
|
|
|
|
template <class T, class Alloc>
|
|
constexpr auto operator<=>(const std::vector<T, Alloc> &lhs, const std::vector<T, Alloc> &rhs)
|
|
{
|
|
// return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), __synth_three_way);
|
|
|
|
auto it1 = lhs.begin();
|
|
auto it2 = rhs.begin();
|
|
|
|
while (it1 != lhs.end() && it2 != rhs.end())
|
|
{
|
|
if (*it1 < *it2)
|
|
return std::strong_ordering::less;
|
|
if (*it1 > *it2)
|
|
return std::strong_ordering::greater;
|
|
++it1;
|
|
++it2;
|
|
}
|
|
|
|
if (it1 == lhs.end() && it2 == rhs.end())
|
|
return std::strong_ordering::equal;
|
|
return (it1 == lhs.end()) ? std::strong_ordering::less : std::strong_ordering::greater;
|
|
}
|
|
|
|
template <class T, class Alloc>
|
|
constexpr void swap(std::vector<T, Alloc> &lhs, std::vector<T, Alloc> &rhs) noexcept(noexcept(noexcept(lhs.swap(rhs))))
|
|
{
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
template <class T, class Alloc, class U>
|
|
constexpr std::vector<T, Alloc>::size_type erase(std::vector<T, Alloc> &c, const U &value)
|
|
{
|
|
auto it = std::remove(c.begin(), c.end(), value);
|
|
auto r = c.end() - it;
|
|
c.erase(it, c.end());
|
|
return r;
|
|
}
|
|
|
|
template <class T, class Alloc, class Pred>
|
|
constexpr std::vector<T, Alloc>::size_type erase_if(std::vector<T, Alloc> &c, Pred pred)
|
|
{
|
|
auto it = std::remove_if(c.begin(), c.end(), pred);
|
|
auto r = c.end() - it;
|
|
c.erase(it, c.end());
|
|
return r;
|
|
}
|
|
}
|