made enumerator_iterator_t compatible with raw pointer iterators

This commit is contained in:
janis 2022-06-30 17:06:38 +01:00
parent 89de73e36a
commit a4f4a0a069

View file

@ -1,66 +1,101 @@
#pragma once #pragma once
#include "types.hpp" #include "types.hpp"
#include <cstddef>
#include <ranges> #include <ranges>
#include <xutility>
namespace util { namespace util {
namespace rg = std::ranges; namespace rg = std::ranges;
template <rg::range R> struct enumerate_iterator_t : rg::iterator_t<R> { template <rg::range R> struct enumerate_iterator_t {
using base = rg::iterator_t<R>; using base = rg::iterator_t<R>;
using enumerator_type = std::size_t; using enumerator_type = std::size_t;
using value_type = std::pair<enumerator_type, rg::range_value_t<R>>; using value_type = std::pair<enumerator_type, rg::range_value_t<R>>;
using difference_type = std::ptrdiff_t;
using reference = using reference =
std::pair<enumerator_type, std::remove_cv_t<rg::range_reference_t<R>>>; std::pair<enumerator_type, std::remove_cv_t<rg::range_reference_t<R>>>;
base base_iter{};
enumerator_type enumerator{}; enumerator_type enumerator{};
enumerate_iterator_t() = default; enumerate_iterator_t() = default;
enumerate_iterator_t(const base &b) : base{b}, enumerator(0) {} enumerate_iterator_t(const base &b) : base_iter{b}, enumerator(0) {}
enumerate_iterator_t(base &&b) : base_iter{std::move(b)}, enumerator(0) {}
auto operator<=>(const enumerate_iterator_t &other) const { auto constexpr operator==(const enumerate_iterator_t &other) const -> bool {
return static_cast<const base &>(*this) <=> return base_iter == other.base_iter;
static_cast<const base &>(other); }
template <std::sentinel_for<base> 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 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 { auto operator++(int) -> enumerate_iterator_t {
const auto result = static_cast<base &>(*this)++; const auto result = *this;
base_iter++;
inc_enumerator(); inc_enumerator();
return result; return result;
} }
auto operator++() -> enumerate_iterator_t & { auto operator++() -> enumerate_iterator_t & {
inc_enumerator(); inc_enumerator();
++static_cast<base &>(*this); ++base_iter;
return (*this); return (*this);
} }
auto operator*() -> reference { auto operator--(int) -> enumerate_iterator_t
return reference(enumerator, *static_cast<base &>(*this)); requires(std::bidirectional_iterator<base>) {
const auto result = *this;
base_iter--;
dec_enumerator();
return result;
} }
auto operator--()
-> enumerate_iterator_t &requires(std::bidirectional_iterator<base>) {
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 { auto operator*() const -> reference {
return reference(enumerator, *static_cast<const base &>(*this)); return reference(enumerator, *base_iter);
} }
}; };
template <rg::range R> template <rg::range R>
class enumerate_view : public rg::view_interface<enumerate_view<R>> { class enumerate_view : public rg::view_interface<enumerate_view<R>> {
R base_{};
isize enumerator{}; isize enumerator{};
enumerate_iterator_t<R> iter_{std::begin(base_)}; enumerate_iterator_t<R> iter_;
enumerate_iterator_t<R> end_;
public: public:
enumerate_view() = default; enumerate_view() = default;
constexpr enumerate_view(R base) : base_(base), iter_(std::begin(base_)) {} constexpr enumerate_view(R base)
: iter_(std::begin(base)), end_(std::end(base)) {}
constexpr R base() const & { return base_; }
constexpr R base() && { return std::move(base_); }
constexpr auto begin() const { return iter_; } constexpr auto begin() const { return iter_; }
constexpr auto end() const { return std::end(base_); } constexpr auto end() const { return end_; }
}; };
namespace detail { namespace detail {