From 892a21cf84cfa21324ee215255ccae4e65bbbf7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20G=C3=BCndling?= Date: Wed, 18 Sep 2024 21:55:37 +0200 Subject: [PATCH] enumerate: compatible to std::iterator_traits --- include/utl/enumerate.h | 47 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/include/utl/enumerate.h b/include/utl/enumerate.h index 0cb554b..35688e3 100644 --- a/include/utl/enumerate.h +++ b/include/utl/enumerate.h @@ -3,6 +3,7 @@ // source: http://reedbeta.com/blog/python-like-enumerate-in-cpp17/ #include +#include #include #include "utl/forward_type.h" @@ -13,6 +14,19 @@ template ())), typename = decltype(std::end(std::declval()))> constexpr auto enumerate(T&& iterable) { struct iterator { + using difference_type = std::ptrdiff_t; + using value_type = + std::tuple::value_type>; + using iterator_category = std::iterator_traits::iterator_category; + using reference = value_type; + using pointer = std::add_pointer_t; + + difference_type operator-(iterator const& o) { + return static_cast(i_) - + static_cast(o.i_); + } + bool operator!=(iterator const& o) const { return iter_ != o.iter_; } void operator++() { @@ -20,6 +34,27 @@ constexpr auto enumerate(T&& iterable) { ++iter_; } + void operator--() + requires(std::bidirectional_iterator) + { + ++i_; + ++iter_; + } + + void operator+=(difference_type const n) + requires(std::random_access_iterator) + { + i_ += static_cast(n); + iter_ += static_cast::difference_type>(n); + } + + void operator-=(difference_type const n) + requires(std::random_access_iterator) + { + i_ = static_cast(static_cast(i_) - n); + iter_ -= static_cast::difference_type>(n); + } + auto operator*() const { using Type = std::decay_t; if constexpr (std::is_pointer_v>) { @@ -35,8 +70,16 @@ constexpr auto enumerate(T&& iterable) { }; struct iterable_wrapper { - auto begin() { return iterator{0U, std::begin(iterable_)}; } - auto end() { return iterator{0U, std::end(iterable_)}; } + auto begin() { + using std::begin; + return iterator{0U, begin(iterable_)}; + } + + auto end() { + using std::end; + return iterator{0U, end(iterable_)}; + } + T iterable_; };