Program Listing for File iterator_tricks.hpp¶
↰ Return to documentation for file (/home/runner/work/Legion-Engine/Legion-Engine/legion/engine/core/containers/iterator_tricks.hpp
)
#pragma once
#include <utility>
#include <functional>
#include <core/platform/platform.hpp>
namespace legion::core
{
template <class T>
struct pair_range
{
using iterator = T;
pair_range(const std::pair<T, T> r) : range(r)
{
}
template<typename ItType>
pair_range(ItType begin, ItType end) : range(std::move(begin), std::move(end))
{
}
L_NODISCARD auto& begin() const
{
return range.first;
}
L_NODISCARD auto& end() const
{
return range.second;
}
std::pair<T, T> range;
};
#if !defined(DOXY_EXCLUDE)
template <class T>
pair_range(std::pair<T, T>)->pair_range<T>;
template <class T>
pair_range(T begin, T end)->pair_range<std::remove_reference_t<T>>;
#endif
template <class It>
bool checked_next(It& iter, It end, std::size_t diff)
{
while (diff-- > 0)
{
if (iter == end) return false;
++iter;
}
return true;
}
template <class KeysIterator, class ValuesIterator>
class key_value_pair_iterator
{
public:
using keys_proxy_type = KeysIterator;
using values_proxy_type = ValuesIterator;
using key_type = typename keys_proxy_type::value_type;
using value_type = typename values_proxy_type::value_type;
using pair_type = std::pair<key_type&, value_type&>;
using const_pair_type = std::pair<const key_type&, const value_type&>;
explicit key_value_pair_iterator(keys_proxy_type keys, values_proxy_type values) : m_key(keys), m_value(values) {}
pair_type operator*()
{
return { std::ref(key()), std::ref(value()) };
}
const_pair_type operator*() const
{
return { std::cref(key()), std::cref(value()) };
}
pair_type operator->()
{
return { std::ref(key()), std::ref(value()) };
}
const_pair_type operator->() const
{
return { std::cref(key()), std::cref(value()) };
}
auto& key()
{
return *m_key;
}
const auto& key() const
{
return *m_key;
}
auto& value()
{
return *m_value;
}
const auto& value() const
{
return *m_value;
}
friend auto operator==(const key_value_pair_iterator& rhs, const key_value_pair_iterator& lhs)
{
return rhs.m_key == lhs.m_key && rhs.m_value == lhs.m_value;
}
friend auto operator!=(const key_value_pair_iterator& rhs, const key_value_pair_iterator& lhs)
{
return rhs.m_key != lhs.m_key || rhs.m_value != lhs.m_value;
}
auto operator++()
{
return key_value_pair_iterator(m_key++, m_value++);
}
auto operator++() const
{
return key_value_pair_iterator(m_key++, m_value++);
}
private:
keys_proxy_type m_key;
values_proxy_type m_value;
};
template <class PairIteratorContainer>
class key_only_iterator
{
public:
using self_proxy_type = typename PairIteratorContainer::iterator;
explicit key_only_iterator(self_proxy_type self) : m_self(self) {}
auto& operator*()
{
return key();
}
const auto& operator*() const
{
return key();
}
auto& operator->()
{
return key();
}
const auto& operator->() const
{
return key();
}
auto& key()
{
return m_self->first;
}
const auto& key() const
{
return m_self->first;
}
friend auto operator==(const key_only_iterator& rhs, const key_only_iterator& lhs)
{
return rhs.m_self == lhs.m_self;
}
friend auto operator!=(const key_only_iterator& rhs, const key_only_iterator& lhs)
{
return rhs.m_self != lhs.m_self;
}
auto operator++()
{
return key_only_iterator(m_self++);
}
auto operator++() const
{
return key_only_iterator(m_self++);
}
private:
self_proxy_type m_self;
};
template <class PairIteratorContainer>
class value_only_iterator
{
public:
using self_proxy_type = typename PairIteratorContainer::iterator;
explicit value_only_iterator(self_proxy_type self) : m_self(std::move(self)) {}
auto& operator*()
{
return value();
}
const auto& operator*() const
{
return value();
}
auto& operator->()
{
return value();
}
const auto& operator->() const
{
return value();
}
auto& value()
{
return m_self->second;
}
const auto& value() const
{
return m_self->second;
}
auto operator++()
{
return value_only_iterator(m_self++);
}
auto operator++() const
{
return value_only_iterator(m_self++);
}
friend auto operator==(const value_only_iterator& rhs, const value_only_iterator& lhs)
{
return rhs.m_self == lhs.m_self;
}
friend auto operator!=(const value_only_iterator& rhs, const value_only_iterator& lhs)
{
return rhs.m_self != lhs.m_self;
}
private:
self_proxy_type m_self;
};
template <class PairIteratorContainer>
class keys_only
{
public:
explicit keys_only(PairIteratorContainer& cont) : m_container(cont) {}
L_NODISCARD auto begin() const
{
return key_only_iterator<PairIteratorContainer>(m_container.begin());
}
L_NODISCARD auto end() const
{
return key_only_iterator<PairIteratorContainer>(m_container.end());
}
private:
PairIteratorContainer& m_container;
};
template <class PairIteratorContainer>
class values_only
{
public:
explicit values_only(PairIteratorContainer& cont) : m_container(cont) {}
L_NODISCARD auto begin() const
{
return value_only_iterator<PairIteratorContainer>(m_container.begin());
}
L_NODISCARD auto end() const
{
return value_only_iterator<PairIteratorContainer>(m_container.end());
}
private:
PairIteratorContainer& m_container;
};
}