Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: CPL - Common Portability Library 4 : * Purpose: Collection enumerator 5 : * Author: Even Rouault, even.rouault at spatialys.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2025, Even Rouault <even.rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #ifndef CPL_ENUMERATE_H 14 : #define CPL_ENUMERATE_H 15 : 16 : #include <cstddef> // size_t 17 : #include <iterator> // std::begin(), std::end() 18 : #include <utility> // std::declval(), std::pair 19 : 20 : namespace cpl 21 : { 22 : 23 : //! @cond Doxygen_Suppress 24 : 25 : template <class T> class Enumerator 26 : { 27 : public: 28 : using TIter = decltype(std::begin(std::declval<T &>())); 29 : 30 : class iterator 31 : { 32 : public: 33 130 : explicit inline iterator(const TIter &it) : m_iter(it) 34 : { 35 130 : } 36 : 37 : inline bool operator==(const iterator &other) const 38 : { 39 : return m_iter == other.m_iter; 40 : } 41 : 42 655 : inline bool operator!=(const iterator &other) const 43 : { 44 655 : return m_iter != other.m_iter; 45 : } 46 : 47 590 : inline iterator &operator++() 48 : { 49 590 : ++m_index; 50 590 : ++m_iter; 51 590 : return *this; 52 : } 53 : 54 : inline iterator operator++(int) 55 : { 56 : iterator before = *this; 57 : ++(*this); 58 : return before; 59 : } 60 : 61 590 : inline auto operator*() const 62 : { 63 590 : return std::pair<size_t, decltype(*m_iter) &>(m_index, *m_iter); 64 : } 65 : 66 : private: 67 : TIter m_iter; 68 : size_t m_index = 0; 69 : }; 70 : 71 65 : explicit inline Enumerator(T &iterable) : m_iterable(iterable) 72 : { 73 65 : } 74 : 75 65 : inline iterator begin() const 76 : { 77 65 : return iterator(std::begin(m_iterable)); 78 : } 79 : 80 65 : inline iterator end() const 81 : { 82 : // We could initialize the m_index to SIZE_T_MAX, but this does not 83 : // really matter as iterator comparison is done on the underlying 84 : // iterator and not the index. 85 65 : return iterator(std::end(m_iterable)); 86 : } 87 : 88 : private: 89 : T &m_iterable; 90 : }; 91 : 92 : //! @endcond 93 : 94 : /** Function returning an eumerator whose values are 95 : * a std::pair of (index: size_t, value: iterable::value_type). 96 : * 97 : * This is similar to Python enumerate() function and C++23 98 : * std::ranges::enumerate() (https://en.cppreference.com/w/cpp/ranges/enumerate_view.html) 99 : * 100 : * \since GDAL 3.13 101 : */ 102 65 : template <class T> inline auto enumerate(T &iterable) 103 : { 104 65 : return Enumerator<T>(iterable); 105 : } 106 : 107 : } // namespace cpl 108 : 109 : #endif