// SPDX-License-Identifier: MIT #ifndef RGBDS_ITERTOOLS_HPP #define RGBDS_ITERTOOLS_HPP #include #include template class EnumSeq { T _start; T _stop; class Iterator { T _value; public: explicit Iterator(T value) : _value(value) {} Iterator &operator++() { _value = static_cast(_value + 1); return *this; } auto operator*() const { return _value; } bool operator==(Iterator const &rhs) const { return _value == rhs._value; } bool operator!=(Iterator const &rhs) const { return !operator==(rhs); } }; public: explicit EnumSeq(T stop) : _start(static_cast(0)), _stop(stop) {} explicit EnumSeq(T start, T stop) : _start(start), _stop(stop) {} Iterator begin() { return Iterator(_start); } Iterator end() { return Iterator(_stop); } }; // This is not a fully generic implementation; its current use cases only require for-loop behavior. // We also assume that all iterators have the same length. template class ZipIterator { std::tuple _iters; public: explicit ZipIterator(std::tuple &&iters) : _iters(iters) {} ZipIterator &operator++() { std::apply([](auto &&...it) { (++it, ...); }, _iters); return *this; } auto operator*() const { return std::apply( [](auto &&...it) { return std::tuple(*it...); }, _iters ); } bool operator==(ZipIterator const &rhs) const { return std::get<0>(_iters) == std::get<0>(rhs._iters); } bool operator!=(ZipIterator const &rhs) const { return !operator==(rhs); } }; template class ZipContainer { std::tuple _containers; public: explicit ZipContainer(Ts &&...containers) : _containers(std::forward(containers)...) {} auto begin() { return ZipIterator(std::apply( [](auto &&...containers) { using std::begin; return std::make_tuple(begin(containers)...); }, _containers )); } auto end() { return ZipIterator(std::apply( [](auto &&...containers) { using std::end; return std::make_tuple(end(containers)...); }, _containers )); } }; // Take ownership of objects and rvalue refs passed to us, but not lvalue refs template using Holder = std:: conditional_t, T, std::remove_cv_t>>; // Does the same number of iterations as the first container's iterator! template static constexpr auto zip(Ts &&...cs) { return ZipContainer...>(std::forward(cs)...); } #endif // RGBDS_ITERTOOLS_HPP