Skip to content

Latest commit

 

History

History
175 lines (137 loc) · 4.79 KB

194.md

File metadata and controls

175 lines (137 loc) · 4.79 KB
Info

Example

int main() {
  std::vector items{1, 2, 3};
  for (auto [i, v] : std::views::enumerate(items)) {
    std::cout << i << v; // prints 011223
  }
}

https://godbolt.org/z/vash36

Puzzle

  • Can you implement a simplified, standard-compliant version of views::enumerate?
/* TODO - views::enumerate */

int main() {
  using namespace boost::ut;

  "enumerate numbers"_test = [i = 0] {
    std::vector items{1, 2, 3};
    for (auto [index, value] : views::enumerate(items)) {
      expect(_i(i) == index and _i(i + 1) == value);
      ++mut(i);
    }
  };

  "enumerate strings"_test = [i = 0] {
    using std::literals::string_literals::operator""s;
    std::vector items{"1"s, "2"s, "3"s};
    for (auto [index, value] : views::enumerate(items)) {
      expect(_i(i) == index and std::to_string(i + 1) == value);
      ++mut(i);
    }
  };
}

https://godbolt.org/z/W85MTj

Solutions

namespace views {
    template <typename C>
    struct enumerate {
        constexpr enumerate(C& c) : container(c) {}

        struct iterator {
            constexpr iterator(C& c) : c_it{std::begin(c)} {}

            constexpr auto operator*() -> std::pair<int, typename C::reference> {
                return {index, *c_it};
            }
            constexpr auto& operator++() { ++c_it; ++index; return *this; }

            typename C::iterator c_it{};
            int index{};
        };

        struct sentinel {
            constexpr sentinel(C& c) : c_it{std::end(c)} {}
            constexpr bool operator==(iterator i) const {
                return i.c_it == c_it;
            }
            typename C::iterator c_it{};
        };

        constexpr auto begin() { return iterator{container}; }
        constexpr auto end() { return sentinel{container}; }

        C& container;
    };
}

https://godbolt.org/z/hMoYhh

namespace views {
template <typename TIterated, typename count_type = unsigned int>
struct enumerate {
    constexpr explicit(true) enumerate(const std::vector<TIterated>& items)
    {
        std::transform(std::begin(items), std::end(items), std::back_inserter(enumerated_items), [](const auto& item) {
            static auto count = std::numeric_limits<count_type>::min();
            return std::pair(count++, item);
        });
    }
    auto begin() const { return std::begin(enumerated_items); }
    auto end() const { return std::end(enumerated_items); }

    std::vector<std::pair<count_type, TIterated>> enumerated_items {};
};
}

https://godbolt.org/z/73G3E5

namespace views {
template<template<class...> class C, class E>
struct enumerate {
    struct iter  {
        iter(size_t index, C<E> const& items) : index(index), items(items) {}
        bool operator!=(iter& other) { return index != other.index; }
        void operator++() { index++; }
        auto operator*() { return std::make_pair(index, *(items.begin()+index)); }
        size_t index;
        const C<E>& items;
    };
    enumerate(C<E> const& items) : items(items) {}
    iter begin() const { return iter(0, items); }
    iter end() const { return iter(items.size(), items);}
    C<E> const& items;
};
}

https://godbolt.org/z/s1cY1K

namespace views {
    template<typename V>
    class enumerate_view {
        V base_;

        class iterator {
            using Base = V;
            using iterator_t = decltype(std::declval<Base>().begin());
            using count_type = decltype(std::declval<Base>().size());
            using reference_t = typename Base::reference;

            iterator_t current_;
            count_type pos_;
        public:
            struct reference {
                const count_type index;
                reference_t value;
            };

            constexpr explicit iterator(iterator_t current, count_type pos) : current_(std::move(current)), pos_(pos) {}

            constexpr decltype(auto) operator*() const { return reference{pos_, *current_}; }

            constexpr iterator& operator++() { ++pos_; ++current_; return *this; }

            friend constexpr bool operator==(const iterator& x, const iterator& y) { return x.current_ == y.current_; }
        };

    public:
        constexpr enumerate_view(V base) : base_(base) {}

        constexpr auto begin() { return iterator(base_.begin(), 0); }
        constexpr auto end() { return iterator(base_.end(), size()); }
        constexpr auto size() { return base_.size(); }
    };

    constexpr auto enumerate(auto values) { return enumerate_view(values); }
} // namespace views

https://godbolt.org/z/4h5MPe