From 9eab6710cead54fa752355e85b33aa549ce9b187 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 12 Jul 2023 11:41:05 +0300 Subject: [PATCH] BAN: Implement ConstIteratorDouble and add it to HashMap This is same as IteratorDouble except it uses const_iterator and does not return non-const references. --- BAN/include/BAN/HashMap.h | 3 ++ BAN/include/BAN/Iterators.h | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/BAN/include/BAN/HashMap.h b/BAN/include/BAN/HashMap.h index e9715c92..38b3afba 100644 --- a/BAN/include/BAN/HashMap.h +++ b/BAN/include/BAN/HashMap.h @@ -31,6 +31,7 @@ namespace BAN using key_type = Key; using value_type = T; using iterator = IteratorDouble; + using const_iterator = ConstIteratorDouble; public: HashMap() = default; @@ -48,6 +49,8 @@ namespace BAN iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); } iterator end() { return iterator(m_buckets.end(), m_buckets.end()); } + const_iterator begin() const { return const_iterator(m_buckets.end(), m_buckets.begin()); } + const_iterator end() const { return const_iterator(m_buckets.end(), m_buckets.end()); } ErrorOr reserve(size_type); diff --git a/BAN/include/BAN/Iterators.h b/BAN/include/BAN/Iterators.h index 421d33a8..65c88a98 100644 --- a/BAN/include/BAN/Iterators.h +++ b/BAN/include/BAN/Iterators.h @@ -266,4 +266,105 @@ namespace BAN friend Container; }; + template typename OuterContainer, template typename InnerContainer, typename Container> + class ConstIteratorDouble + { + public: + using Inner = InnerContainer; + using Outer = OuterContainer; + + public: + ConstIteratorDouble() = default; + ConstIteratorDouble(const IteratorDouble& other) + : m_outer_end(other.m_outer_end) + , m_outer_current(other.m_outer_current) + , m_inner_current(other.m_inner_current) + { + } + + const T& operator*() const + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + return m_inner_current.operator*(); + } + + const T* operator->() const + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + return m_inner_current.operator->(); + } + + ConstIteratorDouble& operator++() + { + ASSERT(*this); + ASSERT(m_outer_current != m_outer_end); + ASSERT(m_inner_current); + m_inner_current++; + find_valid_or_end(); + return *this; + } + ConstIteratorDouble operator++(int) + { + auto temp = *this; + ++(*this); + return temp; + } + + bool operator==(const ConstIteratorDouble& other) const + { + if (!*this || !other) + return false; + if (m_outer_end != other.m_outer_end) + return false; + if (m_outer_current != other.m_outer_current) + return false; + if (m_outer_current == m_outer_end) + return true; + return m_inner_current == other.m_inner_current; + } + bool operator!=(const ConstIteratorDouble& other) const + { + return !(*this == other); + } + + operator bool() const + { + return m_outer_end && m_outer_current; + } + + private: + ConstIteratorDouble(Outer::const_iterator outer_end, Outer::const_iterator outer_current) + : m_outer_end(outer_end) + , m_outer_current(outer_current) + { + if (outer_current != outer_end) + { + m_inner_current = m_outer_current->begin(); + find_valid_or_end(); + } + } + + void find_valid_or_end() + { + while (m_inner_current == m_outer_current->end()) + { + m_outer_current++; + if (m_outer_current == m_outer_end) + break; + m_inner_current = m_outer_current->begin(); + } + } + + private: + Outer::const_iterator m_outer_end; + Outer::const_iterator m_outer_current; + Inner::const_iterator m_inner_current; + + friend Container; + }; + }