diff options
| author | Frank LENORMAND <lenormf@gmail.com> | 2021-10-21 10:52:08 +0200 |
|---|---|---|
| committer | Frank LENORMAND <lenormf@gmail.com> | 2021-10-21 10:58:46 +0200 |
| commit | 0af234a3293c632479ed708388fd73547851a9fd (patch) | |
| tree | b70a942f5dcd26c6747b22aa1d49e746c1911025 /src | |
| parent | 689553c2e9b953a9d3822528d4ad858af95fb6a2 (diff) | |
src: Implement the `enumerate()` range filter
Diffstat (limited to 'src')
| -rw-r--r-- | src/ranges.hh | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/ranges.hh b/src/ranges.hh index bd3edd9b..3480cab9 100644 --- a/src/ranges.hh +++ b/src/ranges.hh @@ -5,6 +5,7 @@ #include <utility> #include <iterator> #include <numeric> +#include <tuple> #include "constexpr_utils.hh" @@ -155,6 +156,53 @@ inline auto filter(Filter f) }); } +template<typename Range> +struct EnumerateView +{ + using RangeIt = IteratorOf<Range>; + + struct Iterator : std::iterator<std::forward_iterator_tag, + typename std::iterator_traits<RangeIt>::value_type> + { + Iterator(size_t index, RangeIt it, RangeIt end) + : m_index{index}, m_it{std::move(it)}, m_end{std::move(end)} {} + + decltype(auto) operator*() { return std::make_tuple(m_index, *m_it); } + Iterator& operator++() { ++m_index; ++m_it; return *this; } + Iterator operator++(int) { auto copy = *this; ++(*this); return copy; } + + friend bool operator==(const Iterator& lhs, const Iterator& rhs) + { + return lhs.m_index == rhs.m_index and lhs.m_it == rhs.m_it; + } + + friend bool operator!=(const Iterator& lhs, const Iterator& rhs) + { + return not (lhs == rhs); + } + + const RangeIt& base() const { return m_it; } + + private: + size_t m_index; + RangeIt m_it; + RangeIt m_end; + }; + + Iterator begin() const { return {0, std::begin(m_range), std::end(m_range)}; } + Iterator end() const { return {std::size(m_range), std::end(m_range), std::end(m_range)}; } + + Range m_range; +}; + +inline auto enumerate() +{ + return make_view_factory([](auto&& range) { + using Range = decltype(range); + return EnumerateView<decay_range<Range>>{std::forward<Range>(range)}; + }); +} + template<typename Range, typename Transform> struct TransformView { |
