I wrote something for this some time ago.
Essentially, you need to wrap the iterator and give it a couple of semantics.
AFAIK, there is nothing like that built into the language. And I do not think that he also has an incentive. You pretty much have to roll on your own.
// Wraps a forward-iterator to produce {value, index} pairs, similar to // python enumerate() template <typename Iterator> struct EnumerateIterator { private: Iterator current; Iterator last; size_t index; bool atEnd; public: typedef decltype(*std::declval<Iterator>()) IteratorValue; typedef pair<IteratorValue const&, size_t> value_type; EnumerateIterator() : index(0), atEnd(true) {} EnumerateIterator(Iterator begin, Iterator end) : current(begin), last(end), index(0) { atEnd = current == last; } EnumerateIterator begin() const { return *this; } EnumerateIterator end() const { return EnumerateIterator(); } EnumerateIterator operator++() { if (!atEnd) { ++current; ++index; atEnd = current == last; } return *this; } value_type operator*() const { return {*current, index}; } bool operator==(EnumerateIterator const& rhs) const { return (atEnd && rhs.atEnd) || (!atEnd && !rhs.atEnd && current == rhs.current && last == rhs.last); } bool operator!=(EnumerateIterator const& rhs) const { return !(*this == rhs); } explicit operator bool() const { return !atEnd; } }; template<typename Iterable> EnumerateIterator<decltype(std::declval<Iterable>().begin())> enumerateIterator(Iterable& list) { return EnumerateIterator<decltype(std::declval<Iterable>().begin())>(list.begin(), list.end()); } template<typename ResultContainer, typename Iterable> ResultContainer enumerateConstruct(Iterable&& list) { ResultContainer res; for (auto el : enumerateIterator(list)) res.push_back(move(el)); return res; }
source share