From cac97fe59df0057f88506257f350e9007d94cc7f Mon Sep 17 00:00:00 2001 From: janis Date: Fri, 1 Jul 2022 01:38:55 +0100 Subject: [PATCH] enumerate fix --- include/ranges/enumerate.hpp | 284 +++++++++++++++++++++++++---------- 1 file changed, 206 insertions(+), 78 deletions(-) diff --git a/include/ranges/enumerate.hpp b/include/ranges/enumerate.hpp index 4cd558b..39e36c8 100644 --- a/include/ranges/enumerate.hpp +++ b/include/ranges/enumerate.hpp @@ -2,125 +2,253 @@ #include "types.hpp" #include #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>>; +template +concept simple_view = // exposition only + rg::view && rg::range && + std::same_as, + std::ranges::iterator_t> && + std::same_as, std::ranges::sentinel_t>; - base base_iter{}; - enumerator_type enumerator{}; +template +requires(rg::view) class enumerate_view + : public rg::view_interface> { +private: + R base_ = R(); - 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) {} +public: + template class iterator; + template class sentinel; - auto constexpr operator==(const enumerate_iterator_t &other) const -> bool { - return base_iter == other.base_iter; + constexpr enumerate_view() = default; + constexpr enumerate_view(R base) : base_(std::move(base)) {} + + constexpr auto size() -> rg::range_difference_t + requires(rg::sized_range) { return rg::size(base_); } + constexpr auto size() const -> rg::range_difference_t + requires(rg::sized_range) { return rg::size(base_); } + + constexpr auto begin() -> iterator { + return iterator{rg::begin(base_), 0}; } - template S> - auto constexpr operator==(const S &sentinel) const -> bool { - return sentinel == base_iter; + constexpr auto begin() const -> iterator { + return iterator{rg::begin(base_), 0}; } - auto constexpr operator<=>(const enumerate_iterator_t &other) const { - return base_iter <=> other.base_iter; + constexpr auto end() { return sentinel(rg::end(base_)); } + + constexpr auto end() requires(rg::common_range &&rg::sized_range) { + return iterator{rg::end(base_), + static_cast>(size())}; } - 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; + constexpr auto end() const requires(rg::range) { + return sentinel{rg::end(base_)}; } - auto operator++() -> enumerate_iterator_t & { - inc_enumerator(); - ++base_iter; - return (*this); + constexpr auto end() const + requires(rg::common_range &&rg::sized_range) { + return iterator{rg::end(base_), + static_cast>(size())}; } - auto operator--(int) -> enumerate_iterator_t - requires(std::bidirectional_iterator) { - const auto result = *this; - base_iter--; - dec_enumerator(); - return result; + constexpr auto base() const -> R &requires(std::copy_constructible) { + return base_; + } + constexpr auto base() -> R && { return std::move(base_); } +}; + +template enumerate_view(R &&) -> enumerate_view>; + +template +requires(rg::view) template class enumerate_view::iterator { +public: + using Base = std::conditional_t; + using iterator_type = rg::iterator_t; + using iterator_category = + typename std::iterator_traits::iterator_category; + using iterator_concept = iterator_category; + + using difference_type = typename rg::range_difference_t; + using enumerator_type = difference_type; + + struct result { + const enumerator_type index; + rg::range_reference_t value; + }; + + using reference = result; + using value_type = result; + +public: + enumerator_type index_ = {}; + iterator_type base_ = iterator_type(); + + iterator() = default; + constexpr explicit iterator(iterator_type base, enumerator_type index = 0) + : base_(std::move(base)), index_(index) {} + constexpr iterator(iterator i) requires Const + && std::convertible_to, rg::iterator_t> + : base_(std::move(i.base_)), index_(std::move(i.index_)) {} + + constexpr rg::iterator_t + base() const &requires std::copyable> { + return base_; + } + constexpr rg::iterator_t base() && { return std::move(base_); } + + constexpr decltype(auto) operator*() const { return result{index_, *base_}; } + + constexpr auto operator++() -> iterator & { + ++index_; + ++base_; + return *this; } - auto operator--() - -> enumerate_iterator_t &requires(std::bidirectional_iterator) { - dec_enumerator(); - --base_iter; - return (*this); + constexpr auto operator++(int) -> void requires(!rg::forward_range) { + ++index_; + ++base_; } - auto constexpr operator+(const difference_type &n) const - -> enumerate_iterator_t { - auto ret = *this; - ret.inc_enumerator(n); - base_iter += n; - - return ret; + constexpr auto operator++(int) -> iterator requires(rg::forward_range) { + const auto tmp = *this; + ++index_; + ++base_; + return tmp; } - auto operator*() -> reference { return reference(enumerator, *base_iter); } - auto operator*() const -> reference { - return reference(enumerator, *base_iter); + constexpr auto operator--() + -> iterator &requires(rg::bidirectional_range) { + --index_; + --base_; + return *this; + } + + constexpr auto operator--(int) -> iterator + requires(rg::bidirectional_range) { + const auto tmp = *this; + --index_; + --base_; + return tmp; + } + + constexpr auto operator+=(difference_type n) + -> iterator &requires(rg::random_access_range) { + index_ += n; + base_ += n; + return *this; + } + + constexpr auto operator-=(difference_type n) + -> iterator &requires(rg::random_access_range) { + index_ -= n; + base_ -= n; + return *this; + } + + friend constexpr auto operator==(const iterator &lhs, const iterator &rhs) + -> bool requires(std::equality_comparable>) { + return lhs.base_ == rhs.base_; + } + + friend constexpr auto operator<(const iterator &lhs, const iterator &rhs) + -> bool requires(rg::random_access_range) { + return lhs.base_ < rhs.base_; + } + friend constexpr auto operator>(const iterator &lhs, const iterator &rhs) + -> bool requires(rg::random_access_range) { + return rhs < lhs; + } + friend constexpr auto operator<=(const iterator &lhs, const iterator &rhs) + -> bool requires(rg::random_access_range) { + return !(rhs < lhs); + } + friend constexpr auto operator>=(const iterator &lhs, const iterator &rhs) + -> bool requires(rg::random_access_range) { + return !(lhs < rhs); + } + + friend constexpr auto operator<=>( + const iterator &lhs, + const iterator &rhs) requires(std::three_way_comparable) { + return lhs.base_ <=> rhs.base_; + } + + friend constexpr auto operator+(const iterator &lhs, difference_type n) + -> iterator requires(rg::random_access_range) { + return iterator{lhs} + n; + } + + friend constexpr auto operator+(difference_type n, const iterator &rhs) + -> iterator requires(rg::random_access_range) { + return n + rhs; + } + + friend constexpr auto operator-(const iterator &lhs, difference_type n) + -> iterator requires(rg::random_access_range) { + return iterator{lhs} -= n; + } + + friend constexpr auto operator-(const iterator &lhs, const iterator &rhs) + -> iterator requires(rg::random_access_range) { + return lhs.base_ - rhs.base_; } }; -template -class enumerate_view : public rg::view_interface> { - isize enumerator{}; - enumerate_iterator_t iter_; - enumerate_iterator_t end_; +template +requires(rg::view) template class enumerate_view::sentinel { +private: + using Base = std::conditional_t; + rg::sentinel_t end_ = rg::sentinel_t(); public: - enumerate_view() = default; + sentinel() = default; + constexpr explicit sentinel(rg::sentinel_t end) : end_(end) {} + constexpr sentinel(sentinel other) requires Const + && std::convertible_to, rg::sentinel_t> + : end_(std::move(other.end_)) {} - constexpr enumerate_view(R base) - : iter_(std::begin(base)), end_(std::end(base)) {} + constexpr auto base() const -> rg::sentinel_t { return end_; } - constexpr auto begin() const { return iter_; } - constexpr auto end() const { return end_; } + friend constexpr auto operator==(const iterator &rhs, + const sentinel &lhs) -> bool { + return rhs.base_ == lhs.end_; + } + + friend constexpr auto operator-(const iterator &rhs, + const sentinel &lhs) + -> rg::range_difference_t { + return rhs.base_ - lhs.end_; + } + friend constexpr auto operator-(const sentinel &rhs, + const iterator &lhs) + -> rg::range_difference_t { + return rhs.end_ - lhs.base_; + } }; 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)); +struct enumerate_view_adaptor { + template constexpr auto operator()(R &&r) const { + return enumerate_view{std::move(r)}; } - constexpr auto operator()() { return enumerate_range_adaptor_closure(); } + template + constexpr friend auto operator|(R &&rng, const enumerate_view_adaptor &) { + return enumerate_view{std::move(rng)}; + } }; - -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; +inline detail::enumerate_view_adaptor enumerate; } // namespace views } // namespace util \ No newline at end of file