mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
committed by
Konstantin Pastbin
parent
c9cbb64f12
commit
76ffc99abd
100
libs/base/range_iterator.hpp
Normal file
100
libs/base/range_iterator.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace base
|
||||
{
|
||||
// RagneItrator allows to write for loops as follows:
|
||||
// for (auto const i : range(N))
|
||||
// ...
|
||||
// for (auto const i : range(M, N))
|
||||
// ...
|
||||
// And initialize stl containers like this:
|
||||
// vector<int> mySequence(MakeRangeIterator(0), MakeRangeIterator(10));
|
||||
template <typename TCounter>
|
||||
struct RangeIterator
|
||||
{
|
||||
explicit RangeIterator(TCounter const current) : m_current(current) {}
|
||||
RangeIterator & operator++() { ++m_current; return *this; }
|
||||
RangeIterator operator++(int) { return RangeIterator(m_current++); }
|
||||
RangeIterator & operator--() { --m_current; return *this; }
|
||||
RangeIterator operator--(int) { return RangeIterator(m_current--); }
|
||||
bool operator==(RangeIterator const & it) const { return m_current == it.m_current; }
|
||||
bool operator!=(RangeIterator const & it) const { return !(*this == it); }
|
||||
|
||||
TCounter operator*() const { return m_current; }
|
||||
|
||||
TCounter m_current;
|
||||
};
|
||||
} // namespace base
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
struct iterator_traits<base::RangeIterator<T>>
|
||||
{
|
||||
using difference_type = T;
|
||||
using value_type = T;
|
||||
using pointer = void;
|
||||
using reference = T;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace base
|
||||
{
|
||||
template <typename TCounter, bool forward>
|
||||
struct RangeWrapper
|
||||
{
|
||||
using value_type = std::remove_cv_t<TCounter>;
|
||||
using iterator_base = RangeIterator<value_type>;
|
||||
using iterator = std::conditional_t<forward, iterator_base, std::reverse_iterator<iterator_base>>;
|
||||
|
||||
RangeWrapper(TCounter const from, TCounter const to):
|
||||
m_begin(from),
|
||||
m_end(to)
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin() const { return iterator(iterator_base(m_begin)); }
|
||||
iterator end() const { return iterator(iterator_base(m_end)); }
|
||||
|
||||
value_type const m_begin;
|
||||
value_type const m_end;
|
||||
};
|
||||
|
||||
// Use this helper to iterate through 0 to `to'.
|
||||
template <typename TCounter>
|
||||
RangeWrapper<TCounter, true> UpTo(TCounter const to)
|
||||
{
|
||||
return {{}, to};
|
||||
}
|
||||
|
||||
// Use this helper to iterate through `from' to `to'.
|
||||
template <typename TCounter>
|
||||
RangeWrapper<TCounter, true> UpTo(TCounter const from, TCounter const to)
|
||||
{
|
||||
return {from, to};
|
||||
}
|
||||
|
||||
// Use this helper to iterate through `from' to 0.
|
||||
template <typename TCounter>
|
||||
RangeWrapper<TCounter, false> DownTo(TCounter const from)
|
||||
{
|
||||
return {from, {}};
|
||||
}
|
||||
|
||||
// Use this helper to iterate through `from' to `to'.
|
||||
template <typename TCounter>
|
||||
RangeWrapper<TCounter, false> DownTo(TCounter const from, TCounter const to)
|
||||
{
|
||||
return {to, from};
|
||||
}
|
||||
|
||||
template <typename TCounter>
|
||||
RangeIterator<TCounter> MakeRangeIterator(TCounter const counter)
|
||||
{
|
||||
return RangeIterator<TCounter>(counter);
|
||||
}
|
||||
} // namespace base
|
||||
Reference in New Issue
Block a user