From a31a04611e9370cffff85ebc1a97748e743520d0 Mon Sep 17 00:00:00 2001 From: Nuri Jung Date: Mon, 11 Dec 2023 19:22:55 +0900 Subject: [PATCH] feat: add CompactMap for bounded integer-like keys --- include/nuri/utils.h | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/include/nuri/utils.h b/include/nuri/utils.h index 8bea4199..676c8c04 100644 --- a/include/nuri/utils.h +++ b/include/nuri/utils.h @@ -245,6 +245,60 @@ namespace internal { return TransformIterator>( it, std::forward(op)); } + + template + class CompactMap { + public: + static_assert(std::is_convertible_v, + "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 + std::pair 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)...); + } + 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 data_; + }; } // namespace internal template , U = 0>