|
@@ -2,6 +2,7 @@
|
|
|
#define __GBLIBCPP_VECTOR__
|
|
|
|
|
|
#include <bits/iter_ops>
|
|
|
+#include <bits/compressed_pair>
|
|
|
|
|
|
#include <functional>
|
|
|
#include <memory>
|
|
@@ -84,27 +85,31 @@ public:
|
|
|
using const_iterator = _iterator<true>;
|
|
|
|
|
|
private:
|
|
|
- T* m_data;
|
|
|
+ impl::compressed_pair<T*, allocator_type> m_data;
|
|
|
size_type m_size;
|
|
|
size_type m_capacity;
|
|
|
- allocator_type m_alloc;
|
|
|
|
|
|
private:
|
|
|
+ constexpr allocator_type& _alloc() noexcept { return m_data.second(); }
|
|
|
+ constexpr const allocator_type& _alloc() const noexcept { return m_data.second(); }
|
|
|
+ constexpr T*& _data() noexcept { return m_data.first(); }
|
|
|
+ constexpr T* const& _data() const noexcept { return m_data.first(); }
|
|
|
+
|
|
|
// assert(n >= m_size)
|
|
|
constexpr void _reallocate_safe(size_type n)
|
|
|
{
|
|
|
T* newptr = nullptr;
|
|
|
if (n)
|
|
|
- newptr = alloc_traits::allocate(m_alloc, n);
|
|
|
+ newptr = alloc_traits::allocate(_alloc(), n);
|
|
|
|
|
|
for (size_t i = 0; i < m_size; ++i) {
|
|
|
if (n)
|
|
|
- alloc_traits::construct(m_alloc, newptr + i, std::move(m_data[i]));
|
|
|
- alloc_traits::destroy(m_alloc, m_data + i);
|
|
|
+ alloc_traits::construct(_alloc(), newptr + i, std::move(_data()[i]));
|
|
|
+ alloc_traits::destroy(_alloc(), _data() + i);
|
|
|
}
|
|
|
|
|
|
- alloc_traits::deallocate(m_alloc, m_data, m_capacity);
|
|
|
- m_data = newptr;
|
|
|
+ alloc_traits::deallocate(_alloc(), _data(), m_capacity);
|
|
|
+ _data() = newptr;
|
|
|
m_capacity = n;
|
|
|
}
|
|
|
|
|
@@ -120,10 +125,10 @@ private:
|
|
|
public:
|
|
|
constexpr vector(void)
|
|
|
noexcept(noexcept(Allocator()))
|
|
|
- : m_data(), m_size(), m_capacity(), m_alloc() {}
|
|
|
+ : m_data{impl::default_construct_t{}}, m_size(), m_capacity() {}
|
|
|
|
|
|
constexpr explicit vector(const Allocator& alloc) noexcept
|
|
|
- : m_data(), m_size(), m_capacity(), m_alloc(alloc) {}
|
|
|
+ : m_data{nullptr, alloc}, m_size(), m_capacity() {}
|
|
|
|
|
|
constexpr vector(size_type n, const T& val,
|
|
|
const Allocator& alloc = Allocator())
|
|
@@ -141,23 +146,22 @@ public:
|
|
|
|
|
|
constexpr vector(const vector& other)
|
|
|
: vector(std::allocator_traits<allocator_type>::
|
|
|
- select_on_container_copy_construction(other.m_alloc))
|
|
|
+ select_on_container_copy_construction(other._alloc()))
|
|
|
{ insert(cbegin(), other.begin(), other.end()); }
|
|
|
|
|
|
constexpr vector(const vector& other, const Allocator& alloc)
|
|
|
: vector(alloc) { insert(cbegin(), other.begin(), other.end()); }
|
|
|
|
|
|
constexpr vector(vector&& other) noexcept
|
|
|
- : m_data(std::exchange(other.m_data, nullptr))
|
|
|
+ : m_data{std::exchange(other._data(), nullptr), std::move(other._alloc())}
|
|
|
, m_size(std::exchange(other.m_size, 0))
|
|
|
- , m_capacity(std::exchange(other.m_capacity, 0))
|
|
|
- , m_alloc(std::move(other.m_alloc)) {}
|
|
|
+ , m_capacity(std::exchange(other.m_capacity, 0)) { }
|
|
|
|
|
|
constexpr vector(vector&& other, const Allocator& alloc)
|
|
|
: vector(alloc)
|
|
|
{
|
|
|
- if (alloc == other.get_allocator()) {
|
|
|
- m_data = std::exchange(other.m_data, nullptr);
|
|
|
+ if (alloc == other._alloc()) {
|
|
|
+ _data() = std::exchange(other._data(), nullptr);
|
|
|
m_size = std::exchange(other.m_size, 0);
|
|
|
m_capacity = std::exchange(other.m_capacity, 0);
|
|
|
} else {
|
|
@@ -185,9 +189,9 @@ public:
|
|
|
|
|
|
if constexpr (alloc_traits::
|
|
|
propagate_on_container_copy_assignment::value) {
|
|
|
- if (m_alloc != other.m_alloc)
|
|
|
+ if (_alloc() != other._alloc())
|
|
|
shrink_to_fit();
|
|
|
- m_alloc = other.m_alloc;
|
|
|
+ _alloc() = other._alloc();
|
|
|
}
|
|
|
|
|
|
insert(cbegin(), other.begin(), other.end());
|
|
@@ -201,10 +205,10 @@ public:
|
|
|
if constexpr (alloc_traits::
|
|
|
propagate_on_container_move_assignment::value) {
|
|
|
shrink_to_fit();
|
|
|
- m_alloc = std::move(other.m_alloc);
|
|
|
+ _alloc() = std::move(other._alloc());
|
|
|
}
|
|
|
else {
|
|
|
- if (m_alloc != other.m_alloc) {
|
|
|
+ if (_alloc() != other._alloc()) {
|
|
|
// TODO: std::move_iterator
|
|
|
for (auto& item : other)
|
|
|
emplace_back(std::move(item));
|
|
@@ -213,7 +217,7 @@ public:
|
|
|
shrink_to_fit();
|
|
|
}
|
|
|
|
|
|
- m_data = std::exchange(other.m_data, nullptr);
|
|
|
+ _data() = std::exchange(other._data(), nullptr);
|
|
|
m_size = std::exchange(other.m_size, 0);
|
|
|
m_capacity = std::exchange(other.m_capacity, 0);
|
|
|
return *this;
|
|
@@ -245,55 +249,55 @@ public:
|
|
|
}
|
|
|
|
|
|
constexpr allocator_type get_allocator(void) const noexcept
|
|
|
- { return m_alloc; }
|
|
|
+ { return _alloc(); }
|
|
|
|
|
|
constexpr reference at(size_type pos)
|
|
|
{
|
|
|
// TODO: exceptions
|
|
|
// if (pos >= sz)
|
|
|
// throw std::out_of_range("vector::at");
|
|
|
- return m_data[pos];
|
|
|
+ return _data()[pos];
|
|
|
}
|
|
|
constexpr const_reference at(size_type pos) const
|
|
|
{
|
|
|
// TODO: exceptions
|
|
|
// if (pos >= sz)
|
|
|
// throw std::out_of_range("vector::at");
|
|
|
- return m_data[pos];
|
|
|
+ return _data()[pos];
|
|
|
}
|
|
|
|
|
|
constexpr reference operator[](size_type pos) noexcept
|
|
|
- { return m_data[pos]; }
|
|
|
+ { return _data()[pos]; }
|
|
|
constexpr const_reference operator[](size_type pos) const noexcept
|
|
|
- { return m_data[pos]; }
|
|
|
+ { return _data()[pos]; }
|
|
|
|
|
|
constexpr reference front() noexcept
|
|
|
- { return m_data[0]; }
|
|
|
+ { return _data()[0]; }
|
|
|
constexpr const_reference front() const noexcept
|
|
|
- { return m_data[0]; }
|
|
|
+ { return _data()[0]; }
|
|
|
constexpr reference back() noexcept
|
|
|
- { return m_data[m_size - 1]; }
|
|
|
+ { return _data()[m_size - 1]; }
|
|
|
constexpr const_reference back() const noexcept
|
|
|
- { return m_data[m_size - 1]; }
|
|
|
+ { return _data()[m_size - 1]; }
|
|
|
|
|
|
constexpr T* data(void) noexcept
|
|
|
- { return m_data; }
|
|
|
+ { return _data(); }
|
|
|
constexpr const T* data(void) const noexcept
|
|
|
- { return m_data; }
|
|
|
+ { return _data(); }
|
|
|
|
|
|
// TODO: std::reverse_iterator
|
|
|
constexpr iterator begin() noexcept
|
|
|
- { return iterator { m_data }; }
|
|
|
+ { return iterator { _data() }; }
|
|
|
constexpr const_iterator begin() const noexcept
|
|
|
- { return const_iterator { m_data }; }
|
|
|
+ { return const_iterator { _data() }; }
|
|
|
constexpr const_iterator cbegin() const noexcept
|
|
|
- { return const_iterator { m_data }; }
|
|
|
+ { return const_iterator { _data() }; }
|
|
|
constexpr iterator end() noexcept
|
|
|
- { return iterator { m_data + m_size }; }
|
|
|
+ { return iterator { _data() + m_size }; }
|
|
|
constexpr const_iterator end() const noexcept
|
|
|
- { return const_iterator { m_data + m_size }; }
|
|
|
+ { return const_iterator { _data() + m_size }; }
|
|
|
constexpr const_iterator cend() const noexcept
|
|
|
- { return const_iterator { m_data + m_size }; }
|
|
|
+ { return const_iterator { _data() + m_size }; }
|
|
|
|
|
|
[[nodiscard]] constexpr bool empty() const noexcept
|
|
|
{ return m_size == 0; }
|
|
@@ -332,22 +336,22 @@ public:
|
|
|
template <typename... Args>
|
|
|
constexpr iterator emplace(const_iterator pos, Args&&... args)
|
|
|
{
|
|
|
- size_type idx = pos - m_data;
|
|
|
+ size_type idx = pos - _data();
|
|
|
|
|
|
- if (!m_data)
|
|
|
+ if (!_data())
|
|
|
reserve(1);
|
|
|
|
|
|
if (m_size == m_capacity)
|
|
|
reserve(m_capacity * 2);
|
|
|
|
|
|
for (size_type i = m_size; i > idx; --i)
|
|
|
- alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-1]));
|
|
|
+ alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i-1]));
|
|
|
|
|
|
- alloc_traits::construct(m_alloc, m_data + idx,
|
|
|
+ alloc_traits::construct(_alloc(), _data() + idx,
|
|
|
std::forward<Args>(args)...);
|
|
|
|
|
|
++m_size;
|
|
|
- return iterator { m_data + idx };
|
|
|
+ return iterator { _data() + idx };
|
|
|
}
|
|
|
|
|
|
constexpr iterator insert(const_iterator pos, T&& val)
|
|
@@ -360,18 +364,18 @@ public:
|
|
|
if (!n)
|
|
|
return pos;
|
|
|
|
|
|
- size_type idx = pos - m_data;
|
|
|
+ size_type idx = pos - _data();
|
|
|
if (!pos)
|
|
|
reserve(n);
|
|
|
|
|
|
if (m_size + n > m_capacity)
|
|
|
reserve(m_size + n);
|
|
|
for (size_type i = m_size + n - 1; i >= idx + n; --i)
|
|
|
- alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));
|
|
|
+ alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i-n]));
|
|
|
for (size_type i = idx; i < idx + n; ++i)
|
|
|
- alloc_traits::construct(m_alloc, m_data + i, val);
|
|
|
+ alloc_traits::construct(_alloc(), _data() + i, val);
|
|
|
m_size += n;
|
|
|
- return iterator { m_data + idx };
|
|
|
+ return iterator { _data() + idx };
|
|
|
}
|
|
|
|
|
|
// TODO: LegacyInputIterator version of this
|
|
@@ -379,7 +383,7 @@ public:
|
|
|
constexpr iterator insert(const_iterator pos,
|
|
|
ForwardIter first, ForwardIter last)
|
|
|
{
|
|
|
- size_type idx = pos - m_data;
|
|
|
+ size_type idx = pos - _data();
|
|
|
size_type n = 0;
|
|
|
|
|
|
ForwardIter tmp = first;
|
|
@@ -395,11 +399,11 @@ public:
|
|
|
if (m_size + n > m_capacity)
|
|
|
reserve(m_size + n);
|
|
|
for (size_type i = m_size + n - 1; i >= idx + n; --i)
|
|
|
- alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i-n]));
|
|
|
+ alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i-n]));
|
|
|
for (size_type i = idx; i < idx + n; ++i)
|
|
|
- alloc_traits::construct(m_alloc, m_data + i, *first++);
|
|
|
+ alloc_traits::construct(_alloc(), _data() + i, *first++);
|
|
|
m_size += n;
|
|
|
- return iterator { m_data + idx };
|
|
|
+ return iterator { _data() + idx };
|
|
|
}
|
|
|
|
|
|
constexpr iterator insert(const_iterator pos, std::initializer_list<T> init)
|
|
@@ -407,12 +411,12 @@ public:
|
|
|
|
|
|
constexpr iterator erase(const_iterator pos)
|
|
|
{
|
|
|
- size_type idx = pos - m_data;
|
|
|
- alloc_traits::destroy(m_alloc, m_data + idx);
|
|
|
+ size_type idx = pos - _data();
|
|
|
+ alloc_traits::destroy(_alloc(), _data() + idx);
|
|
|
for (size_type i = idx; i < m_size - 1; ++i)
|
|
|
- alloc_traits::construct(m_alloc, m_data + i, std::move(m_data[i+1]));
|
|
|
+ alloc_traits::construct(_alloc(), _data() + i, std::move(_data()[i+1]));
|
|
|
--m_size;
|
|
|
- return iterator { m_data + idx };
|
|
|
+ return iterator { _data() + idx };
|
|
|
}
|
|
|
|
|
|
constexpr iterator erase(const_iterator first, const_iterator last)
|
|
@@ -421,15 +425,15 @@ public:
|
|
|
if (!n)
|
|
|
return last;
|
|
|
|
|
|
- size_type idx = first - m_data;
|
|
|
+ size_type idx = first - _data();
|
|
|
for (size_type i = idx; i < idx + n; ++i)
|
|
|
- alloc_traits::destroy(m_alloc, m_data + i);
|
|
|
+ alloc_traits::destroy(_alloc(), _data() + i);
|
|
|
|
|
|
for (size_type i = idx; i < m_size - n; ++i)
|
|
|
- m_alloc.construct(m_data + i, std::move(m_data[i+n]));
|
|
|
+ _alloc().construct(_data() + i, std::move(_data()[i+n]));
|
|
|
|
|
|
m_size -= n;
|
|
|
- return iterator { m_data + idx };
|
|
|
+ return iterator { _data() + idx };
|
|
|
}
|
|
|
|
|
|
constexpr void push_back(const T& val) { insert(cend(), val); }
|
|
@@ -446,8 +450,8 @@ public:
|
|
|
|| alloc_traits::is_always_equal::value)
|
|
|
{
|
|
|
if (alloc_traits::propagate_on_container_swap::value)
|
|
|
- std::swap(m_alloc, other.m_alloc);
|
|
|
- std::swap(m_data, other.m_data);
|
|
|
+ std::swap(_alloc(), other.m_alloc);
|
|
|
+ std::swap(_data(), other.m_data);
|
|
|
std::swap(m_size, other.m_size);
|
|
|
std::swap(m_capacity, other.m_capacity);
|
|
|
}
|