91 lines
2.4 KiB
C++
91 lines
2.4 KiB
C++
#pragma once
|
|
#include "types.hpp"
|
|
#include <ranges>
|
|
|
|
|
|
namespace util {
|
|
namespace rg = std::ranges;
|
|
|
|
template <rg::range R> struct enumerate_iterator_t : rg::iterator_t<R> {
|
|
using base = rg::iterator_t<R>;
|
|
using enumerator_type = std::size_t;
|
|
using value_type = std::pair<enumerator_type, rg::range_value_t<R>>;
|
|
using reference =
|
|
std::pair<enumerator_type, std::remove_cv_t<rg::range_reference_t<R>>>;
|
|
|
|
enumerator_type enumerator{};
|
|
|
|
enumerate_iterator_t() = default;
|
|
enumerate_iterator_t(const base &b) : base{b}, enumerator(0) {}
|
|
|
|
auto operator<=>(const enumerate_iterator_t &other) const {
|
|
return static_cast<const base &>(*this) <=>
|
|
static_cast<const base &>(other);
|
|
}
|
|
|
|
auto inc_enumerator() -> void { enumerator++; }
|
|
|
|
auto operator++(int) -> enumerate_iterator_t {
|
|
const auto result = static_cast<base &>(*this)++;
|
|
inc_enumerator();
|
|
return result;
|
|
}
|
|
|
|
auto operator++() -> enumerate_iterator_t & {
|
|
inc_enumerator();
|
|
++static_cast<base &>(*this);
|
|
return (*this);
|
|
}
|
|
|
|
auto operator*() -> reference {
|
|
return reference(enumerator, *static_cast<base &>(*this));
|
|
}
|
|
auto operator*() const -> reference {
|
|
return reference(enumerator, *static_cast<const base &>(*this));
|
|
}
|
|
};
|
|
|
|
template <rg::range R>
|
|
class enumerate_view : public rg::view_interface<enumerate_view<R>> {
|
|
R base_{};
|
|
isize enumerator{};
|
|
enumerate_iterator_t<R> iter_{std::begin(base_)};
|
|
|
|
public:
|
|
enumerate_view() = default;
|
|
|
|
constexpr enumerate_view(R base) : base_(base), iter_(std::begin(base_)) {}
|
|
|
|
constexpr R base() const & { return base_; }
|
|
constexpr R base() && { return std::move(base_); }
|
|
|
|
constexpr auto begin() const { return iter_; }
|
|
constexpr auto end() const { return std::end(base_); }
|
|
};
|
|
|
|
namespace detail {
|
|
struct enumerate_range_adaptor_closure {
|
|
template <rg::viewable_range R> constexpr auto operator()(R &&r) const {
|
|
return enumerate_view(std::forward<R>(r));
|
|
}
|
|
};
|
|
|
|
struct enumerate_range_adaptor {
|
|
template <rg::viewable_range R> constexpr auto operator()(R &&r) {
|
|
return enumerate_view(std::forward<R>(r));
|
|
}
|
|
|
|
constexpr auto operator()() { return enumerate_range_adaptor_closure(); }
|
|
};
|
|
|
|
template <rg::viewable_range R>
|
|
constexpr auto operator|(R &&r, enumerate_range_adaptor_closure const &a) {
|
|
return a(std::forward<R>(r));
|
|
}
|
|
} // namespace detail
|
|
|
|
namespace views {
|
|
inline detail::enumerate_range_adaptor_closure enumerate;
|
|
} // namespace views
|
|
|
|
} // namespace util
|