mijin2/source/mijin/util/iterators.hpp

91 lines
2.1 KiB
C++

#pragma once
#if !defined(MIJIN_UTIL_ITERATORS_HPP_INCLUDED)
#define MIJIN_UTIL_ITERATORS_HPP_INCLUDED 1
#include <cstddef>
#include <tuple>
namespace mijin
{
template<typename TIdx, typename TIterator>
struct EnumeratingIterator
{
TIdx idx;
TIterator base;
EnumeratingIterator(TIdx idx_, TIterator base_) noexcept : idx(idx_), base(base_) {}
EnumeratingIterator(const EnumeratingIterator&) noexcept = default;
EnumeratingIterator& operator=(const EnumeratingIterator&) noexcept = default;
auto operator*() const noexcept
{
return std::tie(idx, *base);
}
EnumeratingIterator& operator++() noexcept
{
++idx;
++base;
return *this;
}
EnumeratingIterator operator++(int) noexcept
{
EnumeratingIterator copy(*this);
++(*this);
return copy;
}
EnumeratingIterator& operator--() noexcept
{
--idx;
--base;
return *this;
}
EnumeratingIterator operator--(int) noexcept
{
EnumeratingIterator copy(*this);
--(*this);
return copy;
}
bool operator==(const EnumeratingIterator& other) const noexcept
{
return base == other.base; // note: ignoring idx so we don't have to find it out for end()
}
bool operator!=(const EnumeratingIterator& other) const noexcept
{
return base != other.base; // note: ignoring idx so we don't have to find it out for end()
}
};
template<typename TIdx, typename TIterator>
EnumeratingIterator(TIdx, TIterator) -> EnumeratingIterator<TIdx, TIterator>;
template<typename TIdx, typename TIterable>
struct Enumeratable
{
TIterable& base;
auto begin() const noexcept
{
return EnumeratingIterator(TIdx(0), base.begin());
}
auto end() const noexcept
{
return EnumeratingIterator(TIdx(0), base.end());
}
};
template<typename TIdx = std::size_t, typename TIterable>
Enumeratable<TIdx, TIterable> enumerate(TIterable& iterable)
{
return {iterable};
}
} // namespace mijin
#endif // MIJIN_UTIL_ITERATORS_HPP_INCLUDED