]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/EnumIterator.h
Remove use of deprecated std::iterator (#1069)
[thirdparty/squid.git] / src / base / EnumIterator.h
CommitLineData
2fefc43c 1/*
bf95c10a 2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
2fefc43c
FC
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#ifndef SQUID_BASE_ENUMITERATOR_H
10#define SQUID_BASE_ENUMITERATOR_H
11
12#include <iterator>
13#include <type_traits>
14
15/** Shared functionality between forward and reverse enum iterators
16 *
17 * This class is not very useful by itself, it contains code shared by
18 * EnumIterator and ReverseEnumIterator.
19 *
20 * \see EnumIterator, ReverseEnumIterator
21 */
22template <typename EnumType>
c3f0885d 23class EnumIteratorBase
2fefc43c
FC
24{
25protected:
26#if HAVE_STD_UNDERLYING_TYPE
27 typedef typename std::underlying_type<EnumType>::type iterator_type;
28#else
29 typedef int iterator_type;
30#endif
31
32public:
c3f0885d
FC
33 using iterator_category = std::bidirectional_iterator_tag;
34 using value_type = EnumType;
35 using difference_type = std::ptrdiff_t;
36 using pointer = EnumType *;
37 using reference = EnumType &;
38
2fefc43c
FC
39 explicit EnumIteratorBase(EnumType e) : current(static_cast<iterator_type>(e)) {}
40
41 bool operator==(const EnumIteratorBase &i) const {
42 return current == i.current;
43 }
44
45 bool operator!=(const EnumIteratorBase &i) const {
46 return current != i.current;
47 }
48
49 EnumType operator*() const {
50 return static_cast<EnumType>(current);
51 }
52protected:
53 iterator_type current;
54};
55
56/** bidirectional iterator over an enum type
57 *
58 * It can be instantiated using any enum (or C++11 strongly-typed enum)
59 * value; the most common expected use scenario has iterators emitted by
60 * EnumRange and WholeEnum via standard begin() and end() calls.
61 *
62 * In order for the iterator to work, it is mandatory that the underlying
63 * enum type's representation values be sequential.
64 *
65 * The iterator does not check for bounds when incrementing or decrementing,
66 * that responsibility is left to the caller.
67 *
68 * \see EnumRange, WholeEnum, ReverseEnumIterator
69 */
70template <typename EnumType>
71class EnumIterator : public EnumIteratorBase<EnumType>
72{
73public:
74 explicit EnumIterator(EnumType e) : EnumIteratorBase<EnumType>(e) {}
75
76 EnumIterator& operator++() {
77 ++ EnumIteratorBase<EnumType>::current;
78 return *this;
79 }
80
81 EnumIterator& operator++(int) {
82 EnumIterator rv(*this);
83 ++ EnumIteratorBase<EnumType>::current;
84 return rv;
85 }
86
87 EnumIterator& operator--() {
88 -- EnumIteratorBase<EnumType>::current;
89 return *this;
90 }
91
92 EnumIterator& operator--(int) {
93 EnumIterator rv(*this);
94 -- EnumIteratorBase<EnumType>::current;
95 return rv;
96 }
97};
98
99/** bidirectional reverse iterator over an enum type
100 *
101 * It can be instantiated using any enum (or C++11 strongly-typed enum)
102 * value; the most common expected use scenario has iterators emitted by
103 * EnumRange and WholeEnum via standard rbegin() and rend() calls.
104 *
105 * In order for the iterator to work, it is mandatory that the underlying
106 * enum type's representation values be sequential.
107 *
108 * The iterator does not check for bounds; behavior is undefined if the iterator
109 * is incremented (or decremented) outside the range representing valid
110 * enum symbols (remember: an enum is not a data structure).
111 *
112 * \see EnumRange, WholeEnum, EnumIterator
113 */
114template <typename EnumType>
115class ReverseEnumIterator : public EnumIteratorBase<EnumType>
116{
117public:
118 explicit ReverseEnumIterator(EnumType e) : EnumIteratorBase<EnumType>(e) {}
119
120 // prefix increment
121 ReverseEnumIterator& operator++() {
122 -- EnumIteratorBase<EnumType>::current;
123 return *this;
124 }
125
126 // postfix increment
127 ReverseEnumIterator& operator++(int) {
128 ReverseEnumIterator rv(*this);
129 -- EnumIteratorBase<EnumType>::current;
130 return rv;
131 }
132
133 // prefix decrement
134 ReverseEnumIterator& operator--() {
135 ++ EnumIteratorBase<EnumType>::current;
136 return *this;
137 }
138
139 // postfix decrement
140 ReverseEnumIterator& operator--(int) {
141 ReverseEnumIterator rv(*this);
142 ++ EnumIteratorBase<EnumType>::current;
143 return rv;
144 }
145};
146
147/** Class expressing a continuous range of an enum for range-for expressions
148 *
149 * This class requires that the underlying enum values be represented by
150 * continuous values of an integral type.
151 * Users will usually not rely on this class directly but on the more convenient
152 * EnumRange function
153 *
154 * \note EnumIterator<enum>(EnumType::firstmember,EnumType::lastmember)
155 * will miss EnumType::lastmember while iterating. If you need to iterate
156 * over all of EnumType, use class WholeEnum.
157 *
158 * \see EnumRange, WholeEnum
159 */
160template <typename EnumType>
161class EnumRangeT
162{
163public:
164 typedef EnumIterator<EnumType> iterator;
165 typedef ReverseEnumIterator<EnumType> reverse_iterator;
166 EnumRangeT(EnumType first, EnumType one_past_last) : begin_(first), end_(one_past_last) { }
167 iterator begin() const { return iterator(begin_);}
168 iterator end() const { return iterator(end_);}
169 reverse_iterator rbegin() const { return ++reverse_iterator(end_); }
170 reverse_iterator rend() const { return ++reverse_iterator(begin_); }
171private:
172 EnumType begin_;
173 EnumType end_;
174};
175
176/** Generate a continuous range of an enum for range-for expressions
177 *
178 * convenience function to deduce the right type for instantiating EnumRangeT.
179 * See EnumRangeT for more detailed documentation and caveats.
180 *
181 * Typical use:
182 * \code
183 * enum class EnumType {
184 * blue, red, yellow, green, pink
185 * };
186 * for (auto enumvalue : EnumRange(EnumType::red,EnumType::green)) {
187 * do_stuff(enumvalue); // will be called twice, with arguments red and yellow
188 * }
189 * \endcode
190 */
191template <typename EnumType>
192EnumRangeT<EnumType> EnumRange(EnumType begin, EnumType one_past_end)
193{
194 return EnumRangeT<EnumType>(begin,one_past_end);
195}
196
197/** Class expressing a continuous range of a whole enum for range-for expressions
198 *
199 * Class for iterating all enum values, from EnumType::enumBegin_ up to, but
200 * not including, EnumType::enumEnd_.
201 *
202 * This class requires that:
203 * - the underlying enum values be represented by continuous values of
204 * an integral type.
205 * - both enumBegin_ and enumEnd_ markers must be present as EnumType values;
206 * - enumBegin_ must have the same representation as the first element of the
207 * enum
208 * - enumEnd_ must have a representation that is one past the last
209 * user-accessible value of the enum.
210 *
211 * Typical use:
212 * \code
213 * enum class EnumType {
214 * enumBegin_ = 0,
215 * first_value = enumBegin_,
216 * second_value,
217 * enumEnd_
218 * };
219 * for(auto enumvalue : WholeEnum<EnumType>()) {
220 * do_stuff();
221 * }
222 * \endcode
223 */
224template <typename EnumType>
225class WholeEnum : public EnumRangeT<EnumType>
226{
227public:
228 WholeEnum() : EnumRangeT<EnumType>(EnumType::enumBegin_, EnumType::enumEnd_) {}
229};
230
231#endif /* SQUID_BASE_ENUMITERATOR_H */
232