#pragma once #include "types.hpp" #include #include #include namespace util { namespace rg = std::ranges; template struct enumerate_iterator_t { using base = rg::iterator_t; using enumerator_type = std::size_t; using value_type = std::pair>; using difference_type = std::ptrdiff_t; using reference = std::pair>>; base base_iter{}; enumerator_type enumerator{}; enumerate_iterator_t() = default; enumerate_iterator_t(const base &b) : base_iter{b}, enumerator(0) {} enumerate_iterator_t(base &&b) : base_iter{std::move(b)}, enumerator(0) {} auto constexpr operator==(const enumerate_iterator_t &other) const -> bool { return base_iter == other.base_iter; } template S> auto constexpr operator==(const S &sentinel) const -> bool { return sentinel == base_iter; } auto constexpr operator<=>(const enumerate_iterator_t &other) const { return base_iter <=> other.base_iter; } auto inc_enumerator() -> void { enumerator++; } auto dec_enumerator() -> void { enumerator--; } auto dec_enumerator(const difference_type &n) -> void { enumerator -= n; } auto operator++(int) -> enumerate_iterator_t { const auto result = *this; base_iter++; inc_enumerator(); return result; } auto operator++() -> enumerate_iterator_t & { inc_enumerator(); ++base_iter; return (*this); } auto operator--(int) -> enumerate_iterator_t requires(std::bidirectional_iterator) { const auto result = *this; base_iter--; dec_enumerator(); return result; } auto operator--() -> enumerate_iterator_t &requires(std::bidirectional_iterator) { dec_enumerator(); --base_iter; return (*this); } auto constexpr operator+(const difference_type &n) const -> enumerate_iterator_t { auto ret = *this; ret.inc_enumerator(n); base_iter += n; return ret; } auto operator*() -> reference { return reference(enumerator, *base_iter); } auto operator*() const -> reference { return reference(enumerator, *base_iter); } }; template class enumerate_view : public rg::view_interface> { isize enumerator{}; enumerate_iterator_t iter_; enumerate_iterator_t end_; public: enumerate_view() = default; constexpr enumerate_view(R base) : iter_(std::begin(base)), end_(std::end(base)) {} constexpr auto begin() const { return iter_; } constexpr auto end() const { return end_; } }; namespace detail { struct enumerate_range_adaptor_closure { template constexpr auto operator()(R &&r) const { return enumerate_view(std::forward(r)); } }; struct enumerate_range_adaptor { template constexpr auto operator()(R &&r) { return enumerate_view(std::forward(r)); } constexpr auto operator()() { return enumerate_range_adaptor_closure(); } }; template constexpr auto operator|(R &&r, enumerate_range_adaptor_closure const &a) { return a(std::forward(r)); } } // namespace detail namespace views { inline detail::enumerate_range_adaptor_closure enumerate; } // namespace views } // namespace util