diff --git a/source/mijin/container/vector_map.hpp b/source/mijin/container/vector_map.hpp index 2247642..40875b8 100644 --- a/source/mijin/container/vector_map.hpp +++ b/source/mijin/container/vector_map.hpp @@ -5,12 +5,10 @@ #define MIJIN_CONTAINER_VECTOR_MAP_HPP_INCLUDED 1 #include +#include #include #include -#include "./boxed_object.hpp" -#include "./optional.hpp" - #include "../internal/common.hpp" namespace mijin @@ -19,87 +17,85 @@ template struct VectorMapIterator { public: + using key_t = TKey; + using value_t = TValue; + using pair_t = std::pair; + struct Pointer + { + pair_t pair; + + constexpr pair_t* operator->() { return &pair; } + }; + + using difference_type = std::ptrdiff_t; + using value_type = std::pair; + using pointer = Pointer; + using reference = value_type; + using iterator_category = std::random_access_iterator_tag; private: - Optional> ref_; + const key_t* key_; + value_t* value_; public: - VectorMapIterator(TKey* key, TValue* value) + constexpr VectorMapIterator(const key_t* key, value_t* value) MIJIN_NOEXCEPT : key_(key), value_(value) { - ref_.emplace(std::tie(*key, *value)); } - VectorMapIterator(const VectorMapIterator& other) MIJIN_NOEXCEPT : VectorMapIterator(&other.ref_->first, &other.ref_->second) {} - ~VectorMapIterator() noexcept + constexpr VectorMapIterator(const VectorMapIterator& other) noexcept = default; + constexpr VectorMapIterator& operator=(const VectorMapIterator& other) MIJIN_NOEXCEPT = default; + + constexpr bool operator==(const VectorMapIterator& other) const MIJIN_NOEXCEPT { return key_ == other.key_; } + constexpr bool operator!=(const VectorMapIterator& other) const MIJIN_NOEXCEPT { return key_ != other.key_; } + + constexpr reference operator*() const MIJIN_NOEXCEPT { - ref_.reset(); + return std::tie(*key_, *value_); + } + constexpr pointer operator->() const MIJIN_NOEXCEPT + { + return {std::tie(*key_, *value_)}; } - VectorMapIterator& operator=(const VectorMapIterator& other) MIJIN_NOEXCEPT + constexpr VectorMapIterator& operator++() MIJIN_NOEXCEPT { - if (this != &other) - { - ref_.reset(); - ref_.emplace(std::tie(other.ref_->first, other.ref_->second)); - } - return *this; - } - - bool operator==(const VectorMapIterator& other) const MIJIN_NOEXCEPT { return &ref_->first == &other.ref_->first; } - bool operator!=(const VectorMapIterator& other) const MIJIN_NOEXCEPT { return &ref_->first != &other.ref_->first; } - - std::pair operator*() const MIJIN_NOEXCEPT - { - return *ref_; - } - const std::pair* operator->() const MIJIN_NOEXCEPT - { - return &*ref_; - } - - VectorMapIterator& operator++() MIJIN_NOEXCEPT - { - TKey* oldKey = &ref_->first; - TValue* oldValue = &ref_->second; - ref_.reset(); - ref_.emplace(std::tie(*(++oldKey), *(++oldValue))); + ++key_; + ++value_; return *this; } - VectorMapIterator operator++(int) const MIJIN_NOEXCEPT + constexpr VectorMapIterator operator++(int) const MIJIN_NOEXCEPT { VectorMapIterator copy(*this); ++(*this); return copy; } - VectorMapIterator& operator--() MIJIN_NOEXCEPT + constexpr VectorMapIterator& operator--() MIJIN_NOEXCEPT { - TKey* oldKey = &ref_->first; - TValue* oldValue = &ref_->second; - ref_.reset(); - ref_.emplace(std::tie(*(--oldKey), *(--oldValue))); + --key_; + --value_; return *this; } - VectorMapIterator operator--(int) const MIJIN_NOEXCEPT + constexpr VectorMapIterator operator--(int) const MIJIN_NOEXCEPT { VectorMapIterator copy(*this); --(*this); return copy; } - VectorMapIterator operator+(difference_type diff) const MIJIN_NOEXCEPT + constexpr VectorMapIterator operator+(difference_type diff) const MIJIN_NOEXCEPT { - return VectorMapIterator(&ref_->first + diff, &ref_->second + diff); + return VectorMapIterator(key_ + diff, value_ + diff); } - VectorMapIterator operator-(difference_type diff) const MIJIN_NOEXCEPT + constexpr VectorMapIterator operator-(difference_type diff) const MIJIN_NOEXCEPT { - return VectorMapIterator(&ref_->first - diff, &ref_->second - diff); + return VectorMapIterator(key_ - diff, value_ - diff); } - difference_type operator-(const VectorMapIterator& other) const MIJIN_NOEXCEPT + constexpr difference_type operator-(const VectorMapIterator& other) const MIJIN_NOEXCEPT { - return &ref_->first - &other.ref_->first; + return key_ - other.key_; } }; @@ -120,61 +116,61 @@ private: std::vector keys_; std::vector values_; public: - explicit VectorMap(TKeyAllocator keyAllocator = {}) + explicit constexpr VectorMap(TKeyAllocator keyAllocator = {}) MIJIN_NOEXCEPT_IF((std::is_nothrow_move_constructible_v && std::is_nothrow_constructible_v)) : keys_(std::move(keyAllocator)), values_(TValueAllocator(keys_.get_allocator())) {} - VectorMap(TKeyAllocator keyAllocator, TValueAllocator valueAllocator) + constexpr VectorMap(TKeyAllocator keyAllocator, TValueAllocator valueAllocator) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v && std::is_nothrow_move_constructible_v) : keys_(std::move(keyAllocator)), values_(std::move(valueAllocator)) {} - VectorMap(const VectorMap&) = default; - VectorMap(VectorMap&&) = default; + constexpr VectorMap(const VectorMap&) = default; + constexpr VectorMap(VectorMap&&) = default; - VectorMap& operator=(const VectorMap&) = default; - VectorMap& operator=(VectorMap&&) = default; - auto operator<=>(const VectorMap& other) const noexcept = default; + constexpr VectorMap& operator=(const VectorMap&) = default; + constexpr VectorMap& operator=(VectorMap&&) = default; + constexpr auto operator<=>(const VectorMap& other) const noexcept = default; template - TValue& operator[](const TIndex& key) + constexpr mapped_type& operator[](const TIndex& key) { auto it = find(key); if (it != end()) { return it->second; } - return emplace(key, TValue()).first->second; + return emplace(key, mapped_type()).first->second; } template - const TValue& operator[](const TIndex& key) const + constexpr const mapped_type& operator[](const TIndex& key) const { return at(key); } - TValue& operator[](TKey&& key) + constexpr mapped_type& operator[](key_type&& key) { auto it = find(key); if (it != end()) { return it->second; } - return emplace(std::move(key), TValue()).first->second; + return emplace(std::move(key), mapped_type()).first->second; } [[nodiscard]] - iterator begin() MIJIN_NOEXCEPT { return {keys_.data(), values_.data()}; } + constexpr iterator begin() MIJIN_NOEXCEPT { return {keys_.data(), values_.data()}; } [[nodiscard]] - const_iterator begin() const MIJIN_NOEXCEPT { return {keys_.data(), values_.data()}; } + constexpr const_iterator begin() const MIJIN_NOEXCEPT { return {keys_.data(), values_.data()}; } [[nodiscard]] - const_iterator cbegin() const MIJIN_NOEXCEPT { return {keys_.data(), values_.data()}; } + constexpr const_iterator cbegin() const MIJIN_NOEXCEPT { return {keys_.data(), values_.data()}; } [[nodiscard]] - iterator end() MIJIN_NOEXCEPT { return {keys_.data() + keys_.size(), values_.data() + values_.size()}; } + constexpr iterator end() MIJIN_NOEXCEPT { return {keys_.data() + keys_.size(), values_.data() + values_.size()}; } [[nodiscard]] - const_iterator end() const MIJIN_NOEXCEPT { return {keys_.data() + keys_.size(), values_.data() + values_.size()}; } + constexpr const_iterator end() const MIJIN_NOEXCEPT { return {keys_.data() + keys_.size(), values_.data() + values_.size()}; } [[nodiscard]] - const_iterator cend() const MIJIN_NOEXCEPT { return {keys_.data() + keys_.size(), values_.data() + values_.size()}; } + constexpr const_iterator cend() const MIJIN_NOEXCEPT { return {keys_.data() + keys_.size(), values_.data() + values_.size()}; } [[nodiscard]] - TValue& at(const TKey& key) + constexpr mapped_type& at(const key_type& key) { auto it = find(key); if (it == end()) @@ -185,7 +181,7 @@ public: } [[nodiscard]] - const TValue& at(const TKey& key) const + constexpr const mapped_type& at(const key_type& key) const { auto it = find(key); if (it == end()) @@ -196,27 +192,29 @@ public: } [[nodiscard]] - bool empty() const MIJIN_NOEXCEPT { return keys_.empty(); } + constexpr bool empty() const MIJIN_NOEXCEPT { return keys_.empty(); } [[nodiscard]] - size_type size() const MIJIN_NOEXCEPT { return keys_.size(); } + constexpr size_type size() const MIJIN_NOEXCEPT { return keys_.size(); } [[nodiscard]] - size_type max_size() const MIJIN_NOEXCEPT { return std::min(keys_.max_size(), values_.max_size()); } - void reserve(std::size_t size) + constexpr size_type max_size() const MIJIN_NOEXCEPT { return std::min(keys_.max_size(), values_.max_size()); } + constexpr void reserve(std::size_t size) { keys_.reserve(size); values_.reserve(size); } - void clear() + constexpr void clear() { keys_.clear(); values_.clear(); } template - std::pair emplace(TArgs&&... args) + constexpr std::pair emplace(TArgs&&... args) + MIJIN_NOEXCEPT_IF((std::is_nothrow_constructible_v, TArgs&&...> + && std::is_nothrow_move_constructible_v && std::is_nothrow_move_constructible_v)) { - std::pair asPair(std::forward(args)...); + std::pair asPair(std::forward(args)...); auto it = find(asPair.first); if (it != end()) { @@ -227,40 +225,40 @@ public: return std::make_pair(iterator(&keys_.back(), &values_.back()), true); } - iterator erase(iterator pos) MIJIN_NOEXCEPT + constexpr iterator erase(iterator pos) MIJIN_NOEXCEPT { const std::ptrdiff_t idx = &pos->first - &keys_[0]; return eraseImpl(idx); } - iterator erase(const_iterator pos) MIJIN_NOEXCEPT + constexpr iterator erase(const_iterator pos) MIJIN_NOEXCEPT { const std::ptrdiff_t idx = &pos->first - &keys_[0]; return eraseImpl(idx); } - iterator erase(iterator first, iterator last) MIJIN_NOEXCEPT + constexpr iterator erase(iterator first, iterator last) MIJIN_NOEXCEPT { const std::ptrdiff_t idx = &first->first - &keys_[0]; const std::ptrdiff_t count = last - first; return eraseImpl(idx, count); } - iterator erase(const_iterator first, const_iterator last) MIJIN_NOEXCEPT + constexpr iterator erase(const_iterator first, const_iterator last) MIJIN_NOEXCEPT { const std::ptrdiff_t idx = &first->first - &keys_[0]; const std::ptrdiff_t count = last - first; return eraseImpl(idx, count); } - iterator eraseAt(std::size_t idx, std::size_t count = 1) MIJIN_NOEXCEPT + constexpr iterator eraseAt(std::size_t idx, std::size_t count = 1) MIJIN_NOEXCEPT { return eraseImpl(static_cast(idx), static_cast(count)); } template [[nodiscard]] - iterator find(const TSearch& key) MIJIN_NOEXCEPT + constexpr iterator find(const TSearch& key) MIJIN_NOEXCEPT { for (std::size_t idx = 0; idx < keys_.size(); ++idx) { @@ -272,39 +270,38 @@ public: return end(); } - template + template [[nodiscard]] - const_iterator find(const TSearch& key) const MIJIN_NOEXCEPT + constexpr const_iterator find(const TSearch& key, TProj proj = {}) const MIJIN_NOEXCEPT { - for (std::size_t idx = 0; idx < keys_.size(); ++idx) - { - if (keys_[idx] == key) - { - return const_iterator(&keys_[idx], &values_[idx]); - } + auto itKey = std::ranges::find(keys_, key, std::move(proj)); + if (itKey == keys_.end()) { + return end(); } - return end(); + const std::ptrdiff_t idx = std::distance(keys_.begin(), itKey); + return const_iterator(&*itKey, &values_[idx]); } + template [[nodiscard]] - bool contains(const TKey& key) const MIJIN_NOEXCEPT + constexpr bool contains(const TSearch& key, TProj proj = {}) const MIJIN_NOEXCEPT { - return std::ranges::contains(keys_, key); + return std::ranges::contains(keys_, key, std::move(proj)); } [[nodiscard]] - std::pair entry(std::size_t idx) MIJIN_NOEXCEPT + constexpr std::pair entry(std::size_t idx) MIJIN_NOEXCEPT { return std::tie(keys_.at(idx), values_.at(idx)); } [[nodiscard]] - std::pair entry(std::size_t idx) const MIJIN_NOEXCEPT + constexpr std::pair entry(std::size_t idx) const MIJIN_NOEXCEPT { return std::tie(keys_.at(idx), values_.at(idx)); } private: - iterator eraseImpl(std::ptrdiff_t idx, std::ptrdiff_t count = 1) MIJIN_NOEXCEPT + constexpr iterator eraseImpl(std::ptrdiff_t idx, std::ptrdiff_t count = 1) MIJIN_NOEXCEPT { auto itKey = keys_.begin() + idx; auto itValue = values_.begin() + idx; @@ -313,6 +310,16 @@ private: return itKey == keys_.end() ? end() : iterator(&*itKey, &*itValue); // cannot dereference the iterators if the last element was removed } }; + +#if 0 +consteval VectorMap testMap() { + VectorMap result; + result.emplace(5, 17); + result[0] = -10; + return result; +}; +static_assert(testMap().at(0) == -10); +#endif } // namespace mijin #endif // MIJIN_CONTAINER_VECTOR_MAP_HPP_INCLUDED