1#ifndef NEFORCE_CORE_CONTAINER_SPARSE_VECTOR_HPP__
2#define NEFORCE_CORE_CONTAINER_SPARSE_VECTOR_HPP__
21NEFORCE_BEGIN_NAMESPACE__
57template <
bool IsConst,
typename SparseVector>
58struct sparse_vector_iterator :
iiterator<sparse_vector_iterator<IsConst, SparseVector>> {
62 using size_type =
typename container_type::size_type;
66 typename container_type::reference>;
68 typename container_type::pointer>;
74 template <
typename,
typename,
typename,
typename,
typename>
75 friend class sparse_vector;
78 sparse_vector_iterator() noexcept = default;
79 ~sparse_vector_iterator() = default;
81 sparse_vector_iterator(const sparse_vector_iterator&) noexcept = default;
82 sparse_vector_iterator& operator=(const sparse_vector_iterator&) noexcept = default;
83 sparse_vector_iterator(sparse_vector_iterator&&) noexcept = default;
84 sparse_vector_iterator& operator=(sparse_vector_iterator&&) noexcept = default;
100 NEFORCE_DEBUG_VERIFY(container_ !=
nullptr,
"Attempting to dereference on null container");
101 NEFORCE_DEBUG_VERIFY(index_ < container_->
size(),
"Attempting to dereference out of boundary");
109 NEFORCE_DEBUG_VERIFY(container_ !=
nullptr,
"Attempting to increment null container");
110 NEFORCE_DEBUG_VERIFY(index_ <= container_->
size(),
"Attempting to increment out of boundary");
118 NEFORCE_DEBUG_VERIFY(container_ !=
nullptr,
"Attempting to decrement null container");
119 NEFORCE_DEBUG_VERIFY(index_ > 0,
"Attempting to decrement before begin");
128 NEFORCE_DEBUG_VERIFY(container_ !=
nullptr,
"Attempting to advance null container");
138 NEFORCE_DEBUG_VERIFY(container_ == rhs.container_,
"Attempting to distance different container");
147 NEFORCE_NODISCARD
bool equal_to(
const sparse_vector_iterator& rhs)
const noexcept {
148 NEFORCE_DEBUG_VERIFY(container_ == rhs.container_,
"Attempting to equal to a different container");
149 return index_ == rhs.index_;
157 NEFORCE_NODISCARD
bool less_than(
const sparse_vector_iterator& rhs)
const noexcept {
158 NEFORCE_DEBUG_VERIFY(container_ == rhs.container_,
"Attempting to less than a different container");
159 return index_ < rhs.index_;
190template <
typename Key,
typename Value,
typename KeyOfValue,
typename Compare,
typename Alloc = allocator<Value>>
208 using iterator = sparse_vector_iterator<false, sparse_vector>;
217 container_type data_;
218 Compare key_compare_{};
219 KeyOfValue extracter_{};
221 template <
bool,
typename>
222 friend struct sparse_vector_iterator;
229 NEFORCE_NODISCARD
const Key& key_of(
const value_type& value)
const noexcept {
return extracter_(value); }
236 NEFORCE_NODISCARD size_type lower_bound_index(
const key_type& key)
const {
238 size_type hi = data_.
size();
240 size_type mid = lo + (hi - lo) / 2;
241 if (key_compare_(key_of(data_[mid]), key)) {
255 NEFORCE_NODISCARD size_type upper_bound_index(
const key_type& key)
const {
257 size_type hi = data_.
size();
259 size_type mid = lo + (hi - lo) / 2;
260 if (key_compare_(key, key_of(data_[mid]))) {
275 iterator insert_at(size_type pos, value_type&& value) {
276 data_.
emplace(data_.
begin() +
static_cast<difference_type
>(pos), _NEFORCE
move(value));
277 return iterator(pos,
this);
286 iterator insert_at(size_type pos,
const value_type& value) {
287 data_.
emplace(data_.
begin() +
static_cast<difference_type
>(pos), value);
288 return iterator(pos,
this);
302 key_compare_(comp) {}
310 key_compare_(other.key_compare_),
311 extracter_(other.extracter_) {}
323 key_compare_ = other.key_compare_;
324 extracter_ = other.extracter_;
335 data_(_NEFORCE
move(other.data_)),
336 key_compare_(_NEFORCE
move(other.key_compare_)),
337 extracter_(_NEFORCE
move(other.extracter_)) {}
348 data_ = _NEFORCE
move(other.data_);
349 key_compare_ = _NEFORCE
move(other.key_compare_);
350 extracter_ = _NEFORCE
move(other.extracter_);
447 NEFORCE_NODISCARD
bool empty() const noexcept {
return data_.empty(); }
463 template <
typename... Args>
466 size_type pos = lower_bound_index(key_of(tmp));
467 if (pos < data_.size() && !key_compare_(key_of(tmp), key_of(data_[pos]))) {
494 template <
typename... Args>
499 if (position !=
end() && position !=
begin()) {
502 if (key_compare_(key_of(*before), k) && key_compare_(k, key_of(*position))) {
503 return insert_at(position.
index(), _NEFORCE
move(tmp));
506 if (position ==
begin() && !data_.empty()) {
507 if (key_compare_(k, key_of(data_.front()))) {
508 return insert_at(0, _NEFORCE
move(tmp));
510 if (!key_compare_(key_of(data_.front()), k)) {
514 if (position ==
end() && !data_.empty()) {
515 if (key_compare_(key_of(data_.back()), k)) {
516 return insert_at(data_.size(), _NEFORCE
move(tmp));
518 if (!key_compare_(k, key_of(data_.back()))) {
519 return iterator(data_.size() - 1,
this);
550 template <
typename Iterator, enable_if_t<is_iter_v<Iterator>,
int> = 0>
552 for (; first != last; ++first) {
563 template <
typename... Args>
566 size_type pos = upper_bound_index(key_of(tmp));
567 return insert_at(pos, _NEFORCE
move(tmp));
591 template <
typename... Args>
596 if (position !=
end() && position !=
begin()) {
599 if (key_compare_(key_of(*before), k) && key_compare_(k, key_of(*position))) {
600 return insert_at(position.
index(), _NEFORCE
move(tmp));
603 if (position ==
begin() && !data_.empty()) {
604 if (key_compare_(k, key_of(data_.front()))) {
605 return insert_at(0, _NEFORCE
move(tmp));
608 if (position ==
end() && !data_.empty()) {
609 if (!key_compare_(k, key_of(data_.back()))) {
610 return insert_at(data_.size(), _NEFORCE
move(tmp));
641 template <
typename Iterator, enable_if_t<is_iter_v<Iterator>,
int> = 0>
643 for (; first != last; ++first) {
669 NEFORCE_DEBUG_VERIFY(position.
container() ==
this,
"Attempting to erase from different container");
670 NEFORCE_DEBUG_VERIFY(position.
index() < data_.size(),
"Attempting to erase out of boundary");
681 "Attempting to erase from different container");
682 if (first ==
begin() && last ==
end()) {
702 if (pos < data_.size() && !key_compare_(key, key_of(data_[pos]))) {
715 if (pos < data_.size() && !key_compare_(key, key_of(data_[pos]))) {
727 return upper_bound_index(key) - lower_bound_index(key);
803 data_.swap(other.data_);
804 _NEFORCE
swap(key_compare_, other.key_compare_);
805 _NEFORCE
swap(extracter_, other.extracter_);
831NEFORCE_END_NAMESPACE__
iterator lower_bound(const key_type &key)
获取第一个不小于指定键的元素位置
const_reverse_iterator rbegin() const noexcept
获取常量反向起始迭代器
iterator insert_equal(iterator position, const value_type &value)
在提示位置附近拷贝插入允许重复键元素
size_type count(const key_type &key) const
统计具有指定键的元素数量
iterator begin() noexcept
获取起始迭代器
const_iterator cend() const noexcept
reverse_iterator rend() noexcept
获取反向结束迭代器
sparse_vector_iterator< true, sparse_vector > const_iterator
sparse_vector_iterator< false, sparse_vector > iterator
iterator insert_unique(iterator position, const value_type &value)
在提示位置附近拷贝插入唯一键元素
void shrink_to_fit()
收缩容量以适应实际大小
const pair< Key, T > & const_reference
_NEFORCE reverse_iterator< iterator > reverse_iterator
pair< iterator, bool > insert_unique(const value_type &value)
拷贝插入唯一键元素
pair< const_iterator, const_iterator > equal_range(const key_type &key) const
获取等于指定键的元素范围(常量版本)
sparse_vector()=default
默认构造函数
sparse_vector & operator=(const sparse_vector &other)
拷贝赋值运算符
const_reverse_iterator rend() const noexcept
获取常量反向结束迭代器
iterator find(const key_type &key)
查找具有指定键的元素
void erase(iterator position)
删除指定位置的元素
sparse_vector(const sparse_vector &other)
拷贝构造函数
iterator emplace_equal_hint(iterator position, Args &&... args)
在提示位置附近构造允许重复键元素
bool equal_to(const sparse_vector &rhs) const noexcept(noexcept(_NEFORCE equal(cbegin(), cend(), rhs.cbegin())))
相等比较
Compare key_compare() const noexcept(is_nothrow_copy_constructible_v< Compare >)
获取键比较函数对象
void insert_equal(Iterator first, Iterator last)
范围插入允许重复键元素
const_reverse_iterator crbegin() const noexcept
pair< iterator, iterator > equal_range(const key_type &key)
获取等于指定键的元素范围
const_iterator lower_bound(const key_type &key) const
获取第一个不小于指定键的元素位置(常量版本)
const_reverse_iterator crend() const noexcept
size_type erase(const key_type &key)
删除所有具有指定键的元素
bool less_than(const sparse_vector &rhs) const noexcept(noexcept(_NEFORCE lexicographical_compare(cbegin(), cend(), rhs.cbegin(), rhs.cend())))
小于比较
const_iterator begin() const noexcept
获取常量起始迭代器
const_iterator upper_bound(const key_type &key) const
获取第一个大于指定键的元素位置(常量版本)
sparse_vector(sparse_vector &&other) noexcept(is_nothrow_move_constructible_v< container_type > &&is_nothrow_move_constructible_v< Compare > &&is_nothrow_move_constructible_v< KeyOfValue >)
移动构造函数
pair< iterator, bool > emplace_unique(Args &&... args)
插入唯一键元素
iterator end() noexcept
获取结束迭代器
size_type size() const noexcept
获取元素数量
const_iterator find(const key_type &key) const
查找具有指定键的元素(常量版本)
iterator emplace_equal(Args &&... args)
插入允许重复键元素
iterator insert_unique(iterator position, value_type &&value)
在提示位置附近移动插入唯一键元素
void reserve(size_type n)
预留容量
bool empty() const noexcept
检查是否为空
const pair< Key, T > * const_pointer
iterator insert_equal(iterator position, value_type &&value)
在提示位置附近移动插入允许重复键元素
pair< iterator, bool > insert_unique(value_type &&value)
移动插入唯一键元素
iterator insert_equal(const value_type &value)
拷贝插入允许重复键元素
iterator emplace_unique_hint(iterator position, Args &&... args)
在提示位置附近构造唯一键元素
const_iterator end() const noexcept
获取常量结束迭代器
void erase(iterator first, iterator last)
删除指定范围内的元素
pair< Key, T > value_type
iterator upper_bound(const key_type &key)
获取第一个大于指定键的元素位置
_NEFORCE reverse_iterator< const_iterator > const_reverse_iterator
size_type max_size() const noexcept
获取最大可能大小
pair< Key, T > & reference
size_type capacity() const noexcept
获取当前容量
ptrdiff_t difference_type
reverse_iterator rbegin() noexcept
获取反向起始迭代器
iterator insert_equal(value_type &&value)
移动插入允许重复键元素
~sparse_vector()=default
析构函数
sparse_vector(const Compare &comp)
构造函数,指定比较函数
const_iterator cbegin() const noexcept
sparse_vector & operator=(sparse_vector &&other) noexcept(is_nothrow_move_assignable_v< container_type >)
移动赋值运算符
void insert_unique(Iterator first, Iterator last)
范围插入唯一键元素
void swap(sparse_vector &other) noexcept(is_nothrow_swappable_v< container_type > &&is_nothrow_swappable_v< Compare > &&is_nothrow_swappable_v< KeyOfValue >)
交换两个稀疏向量的内容
constexpr iterator begin() noexcept
获取起始迭代器
constexpr size_type size() const noexcept
获取当前元素数量
constexpr void emplace(iterator position, Args &&... args)
在指定位置构造元素
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr bool is_object_v
is_object的便捷变量模板
constexpr bool equal(Iterator1 first1, Iterator1 last1, Iterator2 first2, BinaryPredicate binary_pred) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(binary_pred(*first1, *first2)))
比较两个范围是否相等
constexpr bool lexicographical_compare(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Compare comp) noexcept(noexcept(++first1) &&noexcept(++first2) &&noexcept(comp(*first1, *first2)) &&noexcept(first1==last1 &&first2 !=last2))
字典序比较两个范围
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
constexpr bool is_nothrow_swappable_v
is_nothrow_swappable的便捷变量模板
constexpr bool is_allocator_v
is_allocator的便捷变量模板
constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小
constexpr bool is_nothrow_move_assignable_v
is_nothrow_move_assignable的便捷变量模板
constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
constexpr bool is_nothrow_move_constructible_v
is_nothrow_move_constructible的便捷变量模板
constexpr bool is_same_v
is_same的便捷变量模板
typename conditional< Test, T1, T2 >::type conditional_t
conditional的便捷别名
size_type index() const noexcept
typename container_type::value_type value_type
值类型
constexpr void increment() noexcept
递增操作
bool equal_to(const sparse_vector_iterator &rhs) const noexcept
相等比较
conditional_t< IsConst, typename container_type::const_pointer, typename container_type::pointer > pointer
指针类型
bool less_than(const sparse_vector_iterator &rhs) const noexcept
小于比较
difference_type distance_to(const sparse_vector_iterator &rhs) const noexcept
计算到另一迭代器的距离
const container_type * container() const noexcept
void advance(difference_type n) noexcept
随机访问递增
typename container_type::difference_type difference_type
差值类型
typename container_type::size_type size_type
大小类型
conditional_t< IsConst, typename container_type::const_reference, typename container_type::reference > reference
引用类型
constexpr void decrement() noexcept
递减操作
random_access_iterator_tag iterator_category
随机访问迭代器
reference dereference() const noexcept
解引用操作
SparseVector container_type
容器类型