#pragma once #include #include #include #include /** \brief Provides a wrapper view around a container, allowing to iterate over it's elements and indices. * Allow writing code like shown below: * * std::vector v = getVector(); * for (const std::pair index_and_value : ext::enumerate(v)) * std::cout << "element " << index_and_value.first << " is " << index_and_value.second << std::endl; */ namespace ext { template struct enumerate_iterator { using traits = typename std::iterator_traits; using iterator_category = typename traits::iterator_category; using value_type = std::pair; using difference_type = typename traits::difference_type; using reference = std::pair; std::size_t idx; It it; enumerate_iterator(const std::size_t idx_, It it_) : idx{idx_}, it{it_} {} auto operator*() const { return reference(idx, *it); } bool operator!=(const enumerate_iterator & other) const { return it != other.it; } enumerate_iterator & operator++() { return ++idx, ++it, *this; } }; template struct enumerate_wrapper { using underlying_iterator = decltype(std::begin(std::declval())); using iterator = enumerate_iterator; Collection & collection; enumerate_wrapper(Collection & collection_) : collection(collection_) {} auto begin() { return iterator(0, std::begin(collection)); } auto end() { return iterator(ext::size(collection), std::end(collection)); } }; template auto enumerate(Collection & collection) { return enumerate_wrapper{collection}; } template auto enumerate(const Collection & collection) { return enumerate_wrapper{collection}; } }