19 using index_type = Index;
23 template <
typename... Args>
24 Entry(
const Index entry_id, Args&&... args)
26 , value(std::forward<Args>(args)...)
34 [[nodiscard]]
bool contains(
const Index
id)
const
38 const std::size_t sparse_index =
static_cast<std::size_t
>(id);
39 if (sparse_index >= sparse_.size())
44 const Index dense_index = sparse_[sparse_index];
45 const std::size_t dense_position =
static_cast<std::size_t
>(dense_index);
46 return dense_index != k_invalid_index && dense_position < dense_.size() && dense_[dense_position].id == id;
49 T& insert_or_assign(
const Index
id, T value)
51 ensure_sparse_size(
id);
55 T& existing = dense_[
static_cast<std::size_t
>(sparse_[
static_cast<std::size_t
>(id)])].value;
56 existing = std::move(value);
60 assert_dense_index_available();
61 sparse_[
static_cast<std::size_t
>(id)] =
static_cast<Index
>(dense_.size());
62 dense_.emplace_back(
id, std::move(value));
63 return dense_.back().value;
66 template <
typename... Args>
67 T& emplace(
const Index
id, Args&&... args)
69 ensure_sparse_size(
id);
73 T& existing = dense_[
static_cast<std::size_t
>(sparse_[
static_cast<std::size_t
>(id)])].value;
74 existing = T(std::forward<Args>(args)...);
78 assert_dense_index_available();
79 sparse_[
static_cast<std::size_t
>(id)] =
static_cast<Index
>(dense_.size());
80 dense_.emplace_back(
id, std::forward<Args>(args)...);
81 return dense_.back().value;
84 bool erase(
const Index
id)
91 const Index dense_index = sparse_[
static_cast<std::size_t
>(id)];
92 const auto last_index =
static_cast<Index
>(dense_.size() - 1);
94 if (dense_index != last_index)
96 std::swap(dense_[
static_cast<std::size_t
>(dense_index)], dense_[
static_cast<std::size_t
>(last_index)]);
97 sparse_[
static_cast<std::size_t
>(dense_[
static_cast<std::size_t
>(dense_index)].id)] = dense_index;
101 sparse_[
static_cast<std::size_t
>(id)] = k_invalid_index;
105 T& at(
const Index
id)
107 ASSERT(contains(
id),
"SparseSet id {} is not present",
static_cast<std::size_t
>(
id));
108 return dense_[
static_cast<std::size_t
>(sparse_[
static_cast<std::size_t
>(id)])].value;
111 const T& at(
const Index
id)
const
113 ASSERT(contains(
id),
"SparseSet id {} is not present",
static_cast<std::size_t
>(
id));
114 return dense_[
static_cast<std::size_t
>(sparse_[
static_cast<std::size_t
>(id)])].value;
117 [[nodiscard]] std::vector<T> values()
const
120 out.reserve(dense_.size());
121 for (
const auto& entry : dense_)
123 out.push_back(entry.value);
128 [[nodiscard]] std::vector<Index> ids()
const
130 std::vector<Index> out;
131 out.reserve(dense_.size());
132 for (
const auto& entry : dense_)
134 out.push_back(entry.id);
145 [[nodiscard]] std::size_t size()
const
147 return dense_.size();
150 [[nodiscard]]
bool empty()
const
152 return dense_.empty();
157 return dense_.begin();
165 return dense_.begin();
173 static constexpr Index k_invalid_index = std::numeric_limits<Index>::max();
175 static void assert_valid_id(
const Index
id)
177 ASSERT(
id != k_invalid_index,
"SparseSet id {} is reserved as the invalid sentinel",
static_cast<std::size_t
>(
id));
180 void ensure_sparse_size(
const Index
id)
184 const std::size_t sparse_index =
static_cast<std::size_t
>(id);
185 if (sparse_index >= sparse_.size())
187 sparse_.resize(sparse_index + 1, k_invalid_index);
191 void assert_dense_index_available()
const
193 ASSERT(dense_.size() <
static_cast<std::size_t
>(k_invalid_index),
"SparseSet dense index overflow");
196 std::vector<Index> sparse_;
197 std::vector<Entry> dense_;