From 3d9d62f3e36f7fce7e057c2cfff4ed0dd4371c2b Mon Sep 17 00:00:00 2001
From: Patrick Wuttke
Date: Tue, 17 Feb 2026 10:23:53 +0100
Subject: [PATCH] Made VectorMap constexpr.
---
source/mijin/container/vector_map.hpp | 199 +++++++++++++-------------
1 file changed, 103 insertions(+), 96 deletions(-)
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