Skip to content

Commit

Permalink
feat: add CompactMap for bounded integer-like keys
Browse files Browse the repository at this point in the history
  • Loading branch information
jnooree committed Dec 12, 2023
1 parent 2d781e8 commit a31a046
Showing 1 changed file with 54 additions and 0 deletions.
54 changes: 54 additions & 0 deletions include/nuri/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,60 @@ namespace internal {
return TransformIterator<Iter, remove_cvref_t<UnaryOp>>(
it, std::forward<UnaryOp>(op));
}

template <class K, class V, V sentinel = -1>
class CompactMap {
public:
static_assert(std::is_convertible_v<K, size_t>,
"Key must be an integer-like type");

using key_type = K;
using mapped_type = V;
using value_type = V;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = V &;
using const_reference = const V &;
using pointer = V *;
using const_pointer = const V *;

CompactMap(size_t cap): data_(cap, sentinel) { }

template <class... Args>
std::pair<pointer, bool> try_emplace(key_type key, Args &&...args) {
handle_resize(key);

reference v = data_[key];
bool isnew = v == sentinel;
if (isnew) {
v = V(std::forward<Args>(args)...);
}
return { &v, isnew };
}

pointer find(key_type key) {
if (key < data_.size()) {
return data_[key] == sentinel ? nullptr : &data_[key];
}
return nullptr;
}

const_pointer find(key_type key) const {
if (key < data_.size()) {
return data_[key] == sentinel ? nullptr : &data_[key];
}
return nullptr;
}

private:
void handle_resize(key_type new_key) {
if (new_key >= data_.size()) {
data_.resize(new_key + 1, sentinel);
}
}

std::vector<V> data_;
};
} // namespace internal

template <class E, class U = internal::underlying_type_t<E>, U = 0>
Expand Down

0 comments on commit a31a046

Please sign in to comment.