cgv
Loading...
Searching...
No Matches
enumerate.h
1#pragma once
2
3#include <iterator>
4
5//#include "lib_begin.h"
6
7namespace cgv {
8namespace utils {
9
10// Extended version of enumerate and count ranges.
11// Original copyright by https://www.numbercrunch.de/blog/2018/02/range-based-for-loops-with-counters/
12
13// Wraps an iterator into a pair of an iterator and an integer index.
14template<typename iterator_type>
16public:
17 using iterator = iterator_type;
18 using reference = typename std::iterator_traits<iterator>::reference;
19 using index_type = typename std::iterator_traits<iterator>::difference_type;
20protected:
21 iterator iter;
22 index_type index = 0;
23public:
24 indexed_iterator() = delete;
25 explicit indexed_iterator(iterator iter, index_type start)
26 : iter(iter), index(start) {}
27 indexed_iterator& operator++() {
28 ++iter;
29 ++index;
30 return *this;
31 }
32 bool operator==(const indexed_iterator& other) const {
33 return iter == other.iter;
34 }
35 bool operator!=(const indexed_iterator& other) const {
36 return iter != other.iter;
37 }
38 std::pair<reference, const index_type&> operator*() const {
39 return { *iter, index };
40 }
41};
42
43// Exposes the index of the wrapped iterator.
44template<typename iterator_type>
45class count_iterator : public indexed_iterator<iterator_type> {
46public:
48 using iterator = typename super::iterator;
49 using index_type = typename super::index_type;
50 count_iterator() = delete;
51 explicit count_iterator(iterator iter, index_type start)
52 : super(iter, start) {}
53 index_type operator*() const {
54 return super::index;
55 }
56};
57
58// Pseudo container, wraps a range given by two iterators [first, last)
59// into a range of count iterators.
60template<typename iterator_type>
62public:
64 using index_type = typename std::iterator_traits<iterator_type>::difference_type;
65private:
66 const iterator_type first, last;
67 const index_type start;
68public:
69 count_range() = delete;
70 explicit count_range(iterator_type first, iterator_type last,
71 index_type start = 0)
72 : first(first), last(last), start(start) {}
73 iterator begin() const {
74 return iterator(first, start);
75 }
76 iterator end() const {
77 return iterator(last, start);
78 }
79};
80
81// Convert a container into a range of count iterators.
82template<typename container_type>
83decltype(auto) count(container_type& content,
84 typename std::iterator_traits<typename container_type::iterator>::difference_type start = 0) {
85 using ::std::begin;
86 using ::std::end;
87 return count_range(begin(content), end(content), start);
88}
89
90// Convert a range given by two iterators [first, last) into a range
91// of count iterators.
92template<typename iterator_type>
93decltype(auto) count(iterator_type first, iterator_type last,
94 typename std::iterator_traits<iterator_type>::difference_type start = 0) {
95 return count_range(first, last, start);
96}
97
98// Convert an initializer list into a range of count iterators.
99template<typename type>
100decltype(auto) count(const std::initializer_list<type>& content,
101 std::ptrdiff_t start = 0) {
102 return count_range(content.begin(), content.end(), start);
103}
104
105// Convert an rvalue reference to an initializer list into a range of count iterators.
106template<typename type>
107decltype(auto) count(std::initializer_list<type>&& content,
108 std::ptrdiff_t start = 0) {
109 // Overloaded count_range constructor must move the list into the count_range object.
110 return count_range(content, start);
111}
112
113// Convert a C-array into a range of count iterators.
114template<typename type, std::size_t N>
115decltype(auto) count(type(&content)[N],
116 std::ptrdiff_t start = 0) {
117 return count_range(content, content + N, start);
118}
119
120// Exposes the iterator and index of the wrapped iterator.
121template<typename iterator_type>
122class enumerate_iterator : public indexed_iterator<iterator_type> {
123public:
125 using iterator = typename super::iterator;
126 using index_type = typename super::index_type;
127 using reference = typename super::reference;
128 enumerate_iterator() = delete;
129 explicit enumerate_iterator(iterator iter, index_type start)
130 : super(iter, start) {}
131 std::pair<reference, const index_type&> operator*() const {
132 return { *super::iter, super::index };
133 }
134};
135
136// Pseudo container, wraps a range given by two iterators [first, last)
137// into a range of enumerate iterators.
138template<typename iterator_type>
140public:
142 using index_type = typename std::iterator_traits<iterator_type>::difference_type;
143private:
144 const iterator_type first, last;
145 const index_type start;
146public:
147 enumerate_range() = delete;
148 explicit enumerate_range(iterator_type first, iterator_type last,
149 index_type start = 0)
150 : first(first), last(last), start(start) {}
151 iterator begin() const {
152 return iterator(first, start);
153 }
154 iterator end() const {
155 return iterator(last, start);
156 }
157};
158
159// Convert a container into a range of enumerate iterators.
160template<typename container_type>
161decltype(auto) enumerate(container_type& content,
162 typename std::iterator_traits<typename container_type::iterator>::difference_type start = 0) {
163 using ::std::begin;
164 using ::std::end;
165 return enumerate_range(begin(content), end(content), start);
166}
167
168// Convert a range given by two iterators [first, last) into a range
169// of enumerate iterators.
170template<typename iterator_type>
171decltype(auto) enumerate(iterator_type first, iterator_type last,
172 typename std::iterator_traits<iterator_type>::difference_type start = 0) {
173 return enumerate_range(first, last, start);
174}
175
176// Convert an initializer list into a range of enumerate iterators.
177template<typename type>
178decltype(auto) enumerate(const std::initializer_list<type>& content,
179 std::ptrdiff_t start = 0) {
180 return enumerate_range(content.begin(), content.end(), start);
181}
182
183// Convert an rvalue reference to an initializer list into a range of enumerate iterators.
184template<typename type>
185decltype(auto) enumerate(std::initializer_list<type>&& content,
186 std::ptrdiff_t start = 0) {
187 // Overloaded enumerate_range constructor must move the list into the enumerate_range object.
188 return enumerate_range(content, start);
189}
190
191// Convert a C-array into a range of enumerate iterators.
192template<typename type, std::size_t N>
193decltype(auto) enumerate(type(&content)[N],
194 std::ptrdiff_t start = 0) {
195 return enumerate_range(content, content + N, start);
196}
197
198
199} // namespace utils
200} // namespace cgv
201
202//#include <cgv/config/lib_end.h>
the cgv namespace
Definition print.h:11