// Copyright 2023 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #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 EnumerateIterator { 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; EnumerateIterator(const std::size_t idx, It it) : idx{idx} , it{it} {} auto operator*() const { return reference(idx, *it); } bool operator!=(const EnumerateIterator & other) const { return it != other.it; } EnumerateIterator & operator++() { return ++idx, ++it, *this; } }; template struct EnumerateWrapper { using underlying_iterator = decltype(std::begin(std::declval())); using iterator = EnumerateIterator; Collection & collection; explicit EnumerateWrapper(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 EnumerateWrapper{collection}; } template auto enumerate(const Collection & collection) { return EnumerateWrapper{collection}; } } // namespace ext