#pragma once #if !defined(MIJIN_UTIL_ITERATORS_HPP_INCLUDED) #define MIJIN_UTIL_ITERATORS_HPP_INCLUDED 1 #include #include namespace mijin { template struct EnumeratingIterator { TIdx idx; TIterator base; EnumeratingIterator(TIdx idx_, TIterator base_) noexcept : idx(idx_), base(base_) {} EnumeratingIterator(const EnumeratingIterator&) noexcept = default; EnumeratingIterator& operator=(const EnumeratingIterator&) noexcept = default; auto operator*() const noexcept { return std::tie(idx, *base); } EnumeratingIterator& operator++() noexcept { ++idx; ++base; return *this; } EnumeratingIterator operator++(int) noexcept { EnumeratingIterator copy(*this); ++(*this); return copy; } EnumeratingIterator& operator--() noexcept { --idx; --base; return *this; } EnumeratingIterator operator--(int) noexcept { EnumeratingIterator copy(*this); --(*this); return copy; } bool operator==(const EnumeratingIterator& other) const noexcept { return base == other.base; // note: ignoring idx so we don't have to find it out for end() } bool operator!=(const EnumeratingIterator& other) const noexcept { return base != other.base; // note: ignoring idx so we don't have to find it out for end() } }; template EnumeratingIterator(TIdx, TIterator) -> EnumeratingIterator; template struct Enumeratable { TIterable& base; auto begin() const noexcept { return EnumeratingIterator(TIdx(0), base.begin()); } auto end() const noexcept { return EnumeratingIterator(TIdx(0), base.end()); } }; template Enumeratable enumerate(TIterable& iterable) { return {iterable}; } } // namespace mijin #endif // MIJIN_UTIL_ITERATORS_HPP_INCLUDED