Skip to content

Commit

Permalink
enumerate: compatible to std::iterator_traits
Browse files Browse the repository at this point in the history
  • Loading branch information
felixguendling committed Sep 18, 2024
1 parent f08f454 commit 892a21c
Showing 1 changed file with 45 additions and 2 deletions.
47 changes: 45 additions & 2 deletions include/utl/enumerate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// source: http://reedbeta.com/blog/python-like-enumerate-in-cpp17/

#include <cstddef>
#include <iterator>
#include <tuple>

#include "utl/forward_type.h"
Expand All @@ -13,13 +14,47 @@ template <typename T, typename TIter = decltype(std::begin(std::declval<T>())),
typename = decltype(std::end(std::declval<T>()))>
constexpr auto enumerate(T&& iterable) {
struct iterator {
using difference_type = std::ptrdiff_t;
using value_type =
std::tuple<std::size_t,
typename std::iterator_traits<TIter>::value_type>;
using iterator_category = std::iterator_traits<TIter>::iterator_category;
using reference = value_type;
using pointer = std::add_pointer_t<value_type>;

difference_type operator-(iterator const& o) {
return static_cast<std::ptrdiff_t>(i_) -
static_cast<std::ptrdiff_t>(o.i_);
}

bool operator!=(iterator const& o) const { return iter_ != o.iter_; }

void operator++() {
++i_;
++iter_;
}

void operator--()
requires(std::bidirectional_iterator<TIter>)
{
++i_;
++iter_;
}

void operator+=(difference_type const n)
requires(std::random_access_iterator<TIter>)
{
i_ += static_cast<std::size_t>(n);
iter_ += static_cast<std::iterator_traits<TIter>::difference_type>(n);
}

void operator-=(difference_type const n)
requires(std::random_access_iterator<TIter>)
{
i_ = static_cast<std::size_t>(static_cast<difference_type>(i_) - n);
iter_ -= static_cast<std::iterator_traits<TIter>::difference_type>(n);
}

auto operator*() const {
using Type = std::decay_t<decltype(*iter_)>;
if constexpr (std::is_pointer_v<std::decay_t<Type>>) {
Expand All @@ -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_;
};

Expand Down

0 comments on commit 892a21c

Please sign in to comment.