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.
This commit is contained in:
Bananymous 2023-07-12 11:41:05 +03:00
parent 4285729d5c
commit 6b0920e8c0
2 changed files with 104 additions and 0 deletions

View File

@ -31,6 +31,7 @@ namespace BAN
using key_type = Key; using key_type = Key;
using value_type = T; using value_type = T;
using iterator = IteratorDouble<Entry, Vector, LinkedList, HashMap>; using iterator = IteratorDouble<Entry, Vector, LinkedList, HashMap>;
using const_iterator = ConstIteratorDouble<Entry, Vector, LinkedList, HashMap>;
public: public:
HashMap() = default; HashMap() = default;
@ -48,6 +49,8 @@ namespace BAN
iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); } iterator begin() { return iterator(m_buckets.end(), m_buckets.begin()); }
iterator end() { return iterator(m_buckets.end(), m_buckets.end()); } 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<void> reserve(size_type); ErrorOr<void> reserve(size_type);

View File

@ -266,4 +266,105 @@ namespace BAN
friend Container; friend Container;
}; };
template<typename T, template <typename> typename OuterContainer, template <typename> typename InnerContainer, typename Container>
class ConstIteratorDouble
{
public:
using Inner = InnerContainer<T>;
using Outer = OuterContainer<Inner>;
public:
ConstIteratorDouble() = default;
ConstIteratorDouble(const IteratorDouble<T, OuterContainer, InnerContainer, Container>& 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;
};
} }