18template<std::movable Value, std::convertible_to<u
int32_t> Key = u
int32_t>
22 static constexpr auto NullIndex = UINT32_MAX;
24 explicit sparse_map(
size_t initialKeyCapacity,
size_t maxKeyCapacity = 65536ull)
25 : m_sparse(initialKeyCapacity, NullIndex),
26 m_initialKeyCapacity{initialKeyCapacity},
27 m_maxKeyCapacity{maxKeyCapacity}
31 auto emplace(Key key,
const Value& value) -> Value&
34 auto& denseIndex = m_sparse.at(
static_cast<size_t>(key));
35 NC_ASSERT(denseIndex == NullIndex,
"Key already exists");
36 denseIndex =
static_cast<uint32_t
>(m_dense.size());
37 m_dense.push_back(key);
38 m_values.push_back(value);
39 return m_values.back();
42 auto emplace(Key key, Value&& value) -> Value&
45 auto& denseIndex = m_sparse.at(
static_cast<size_t>(key));
46 NC_ASSERT(denseIndex == NullIndex,
"Key already exists");
47 denseIndex =
static_cast<uint32_t
>(m_dense.size());
48 m_dense.push_back(key);
49 m_values.push_back(std::move(value));
50 return m_values.back();
53 auto erase(Key key) ->
bool
58 const auto normalizedKey =
static_cast<size_t>(key);
59 const auto swappedSparse = m_dense.back();
60 const auto toRemoveDense = m_sparse.at(normalizedKey);
61 m_sparse.at(swappedSparse) = toRemoveDense;
62 m_sparse.at(normalizedKey) = NullIndex;
63 m_dense.at(toRemoveDense) = m_dense.back();
65 m_values.at(toRemoveDense) = std::move(m_values.back());
70 auto contains(Key key)
const noexcept ->
bool
72 const auto normalizedKey =
static_cast<size_t>(key);
73 return normalizedKey < m_sparse.size()
74 ? m_sparse[normalizedKey] != NullIndex
78 void reserve(
size_t capacity)
80 m_dense.reserve(capacity);
81 m_values.reserve(capacity);
84 void reserve_keys(
size_t capacity)
86 m_sparse.reserve(capacity);
91 m_sparse = std::vector<uint32_t>(m_initialKeyCapacity, NullIndex);
93 m_dense.shrink_to_fit();
95 m_values.shrink_to_fit();
98 auto at(Key key) -> Value& {
return m_values.at(m_sparse.at(key)); }
99 auto at(Key key)
const ->
const Value& {
return m_values.at(m_sparse.at(key)); }
100 auto keys()
noexcept -> std::span<Key> {
return m_dense; }
101 auto keys()
const noexcept -> std::span<const Key> {
return m_dense; }
102 auto values()
noexcept -> std::span<Value> {
return m_values; }
103 auto values()
const noexcept -> std::span<const Value> {
return m_values; }
104 auto size()
const noexcept ->
size_t {
return m_values.size(); }
105 auto empty()
const noexcept ->
bool {
return m_values.empty(); }
106 auto size_keys()
const noexcept {
return m_sparse.size(); }
107 auto capacity()
const noexcept {
return m_values.capacity(); }
108 auto capacity_keys()
const noexcept {
return m_sparse.capacity(); }
110 auto begin() {
return m_values.begin(); }
111 auto begin()
const {
return m_values.begin(); }
112 auto cbegin()
const {
return m_values.cbegin(); }
113 auto end() {
return m_values.end(); }
114 auto end()
const {
return m_values.end(); }
115 auto cend()
const {
return m_values.cend(); }
118 std::vector<uint32_t> m_sparse;
119 std::vector<Key> m_dense;
120 std::vector<Value> m_values;
121 size_t m_initialKeyCapacity;
122 size_t m_maxKeyCapacity;
124 auto dense_index(Key key)
const -> uint32_t
126 return m_sparse.at(
static_cast<size_t>(key));
129 void ensure_capacity(Key key)
131 const auto normalizedKey =
static_cast<size_t>(key);
132 const auto currentSize = m_sparse.size();
133 if (normalizedKey >= currentSize)
135 if (normalizedKey > m_maxKeyCapacity)
136 throw NcError{
"Max key capacity exceeded"};
138 const auto growthSize = std::min<size_t>(currentSize * 2ull, m_maxKeyCapacity);
139 const auto newSize = std::max<size_t>(growthSize, normalizedKey + 1ull);
140 m_sparse.resize(newSize, NullIndex);
Common exception type used throughout NcEngine.
Definition: NcError.h:18
A map-like container with O(1) insertion, removal, and lookup and O(N) iteration.
Definition: SparseMap.h:20