3#include <mixedbag/exports.h>
5#include <memory_resource>
21 template <
typename T,
typename SizeT = std::
size_t,
bool Checked = true>
24 using allocator_type = std::pmr::polymorphic_allocator<>;
25 using iterator =
typename std::pmr::vector<T>::iterator;
26 using const_iterator =
typename std::pmr::vector<T>::const_iterator;
27 using value_type =
typename std::pmr::vector<T>::value_type;
28 using reference =
typename std::pmr::vector<T>::reference;
29 using pointer =
typename std::pmr::vector<T>::pointer;
30 using difference_type =
typename std::pmr::vector<T>::difference_type;
31 using size_type = SizeT;
44 : pos_(other.pos_, allocator)
45 , data_(other.data_, allocator)
49 : pos_(std::move(other.pos_), allocator)
50 , data_(std::move(other.data_), allocator)
73 pos_ = std::move(other.pos_);
74 data_ = std::move(other.data_);
82 return data_.get_allocator();
87 template <
typename... Args>
88 reference
emplace(size_type index, Args... args)
90 prepare_insert(index);
92 data_.emplace_back(std::forward<Args...>(args...));
97 reference
insert(size_type index,
const value_type& val)
99 prepare_insert(index);
101 data_.push_back(val);
109 if (pos_[index] != data_.size() - 1) {
111 const auto toRemove = pos_[index];
112 std::swap(data_[toRemove], data_.back());
115 const auto it = std::ranges::find(pos_, data_.size() - 1);
120 pos_[index] = InvalidPos;
125 [[nodiscard]] size_type
size() const noexcept
127 return static_cast<size_type
>(data_.size());
131 [[nodiscard]]
bool empty() const noexcept
133 return data_.empty();
151 [[nodiscard]]
const value_type&
operator[](size_type index)
const
154 return data_[pos_[index]];
160 return data_[pos_[index]];
166 [[nodiscard]] iterator
begin() noexcept
168 return data_.begin();
171 [[nodiscard]] iterator
end() noexcept
176 [[nodiscard]] const_iterator
cbegin() const noexcept
178 return data_.cbegin();
181 [[nodiscard]] const_iterator
cend() const noexcept
195 using ResultType = std::compare_three_way_result_t<value_type>;
197 const auto minLen = std::min(pos_.size(), other.pos_.size());
198 for (
auto i = size_type{0}; i < minLen; ++i) {
199 if (pos_[i] == InvalidPos && other.pos_[i] == InvalidPos)
201 if (pos_[i] == InvalidPos)
202 return ResultType::greater;
203 if (other.pos_[i] == InvalidPos)
204 return ResultType::less;
205 if (
auto cmpResult = data_[pos_[i]] <=> other.data_[other.pos_[i]]; cmpResult != ResultType::equal)
209 if (data_.size() < other.data_.size())
210 return ResultType::less;
211 if (data_.size() > other.data_.size())
212 return ResultType::greater;
214 return ResultType::equal;
219 if (data_.size() != other.data_.size())
222 const auto minLen = std::min(pos_.size(), other.pos_.size());
223 for (
auto i = size_type{0}; i < minLen; ++i) {
224 if (pos_[i] == InvalidPos && other.pos_[i] == InvalidPos)
226 if (pos_[i] == InvalidPos || other.pos_[i] == InvalidPos)
228 if (data_[pos_[i]] != other.data_[other.pos_[i]])
237 void prepare_insert(size_type index)
239 if constexpr (Checked) {
240 if (index == InvalidPos)
241 throw std::runtime_error(
"sparse_vector: insert - index out of range");
244 if (index >= pos_.size())
245 pos_.resize(index + 1, InvalidPos);
247 if constexpr (Checked) {
248 if (pos_[index] != InvalidPos)
249 throw std::runtime_error(
"sparse_vector: insert - element already exists at specified index");
252 pos_[index] =
static_cast<size_type
>(data_.size());
255 void check_access(size_type index)
const
257 if constexpr (Checked) {
258 if (pos_.size() <= index)
259 throw std::runtime_error(
"sparse_vector: access - index out of range");
261 if (pos_[index] == InvalidPos)
262 throw std::runtime_error(
"sparse_vector: access - no data at specified index");
266 static constexpr size_type InvalidPos = ~(size_type(0));
267 std::pmr::vector<size_type> pos_;
268 std::pmr::vector<T> data_;
Definition sparse_vector.hxx:22
void erase(size_type index)
Definition sparse_vector.hxx:106
const_iterator cend() const noexcept
Definition sparse_vector.hxx:181
bool operator==(const sparse_vector &other) const noexcept
Definition sparse_vector.hxx:217
iterator begin() noexcept
Definition sparse_vector.hxx:166
const_iterator cbegin() const noexcept
Definition sparse_vector.hxx:176
value_type & operator[](size_type index)
Definition sparse_vector.hxx:157
auto operator<=>(const sparse_vector &other) const noexcept -> std::compare_three_way_result_t< value_type >
Definition sparse_vector.hxx:193
void reserve_index(size_type size)
Definition sparse_vector.hxx:138
void reserve_data(size_type size)
Definition sparse_vector.hxx:143
iterator end() noexcept
Definition sparse_vector.hxx:171
allocator_type get_allocator() const
Definition sparse_vector.hxx:80
bool empty() const noexcept
Definition sparse_vector.hxx:131
sparse_vector & operator=(sparse_vector &&other) noexcept
Definition sparse_vector.hxx:68
sparse_vector & operator=(const sparse_vector &other)
Definition sparse_vector.hxx:58
reference insert(size_type index, const value_type &val)
Definition sparse_vector.hxx:97
size_type size() const noexcept
Definition sparse_vector.hxx:125
reference emplace(size_type index, Args... args)
Definition sparse_vector.hxx:88
const value_type & operator[](size_type index) const
Definition sparse_vector.hxx:151