2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_BASE_ENUMITERATOR_H
10 #define SQUID_BASE_ENUMITERATOR_H
13 #include <type_traits>
15 /** Shared functionality between forward and reverse enum iterators
17 * This class is not very useful by itself, it contains code shared by
18 * EnumIterator and ReverseEnumIterator.
20 * \see EnumIterator, ReverseEnumIterator
22 template <typename EnumType
>
23 class EnumIteratorBase
: public std::iterator
<std::bidirectional_iterator_tag
, EnumType
>
26 #if HAVE_STD_UNDERLYING_TYPE
27 typedef typename
std::underlying_type
<EnumType
>::type iterator_type
;
29 typedef int iterator_type
;
33 explicit EnumIteratorBase(EnumType e
) : current(static_cast<iterator_type
>(e
)) {}
35 bool operator==(const EnumIteratorBase
&i
) const {
36 return current
== i
.current
;
39 bool operator!=(const EnumIteratorBase
&i
) const {
40 return current
!= i
.current
;
43 EnumType
operator*() const {
44 return static_cast<EnumType
>(current
);
47 iterator_type current
;
50 /** bidirectional iterator over an enum type
52 * It can be instantiated using any enum (or C++11 strongly-typed enum)
53 * value; the most common expected use scenario has iterators emitted by
54 * EnumRange and WholeEnum via standard begin() and end() calls.
56 * In order for the iterator to work, it is mandatory that the underlying
57 * enum type's representation values be sequential.
59 * The iterator does not check for bounds when incrementing or decrementing,
60 * that responsibility is left to the caller.
62 * \see EnumRange, WholeEnum, ReverseEnumIterator
64 template <typename EnumType
>
65 class EnumIterator
: public EnumIteratorBase
<EnumType
>
68 explicit EnumIterator(EnumType e
) : EnumIteratorBase
<EnumType
>(e
) {}
70 EnumIterator
& operator++() {
71 ++ EnumIteratorBase
<EnumType
>::current
;
75 EnumIterator
& operator++(int) {
76 EnumIterator
rv(*this);
77 ++ EnumIteratorBase
<EnumType
>::current
;
81 EnumIterator
& operator--() {
82 -- EnumIteratorBase
<EnumType
>::current
;
86 EnumIterator
& operator--(int) {
87 EnumIterator
rv(*this);
88 -- EnumIteratorBase
<EnumType
>::current
;
93 /** bidirectional reverse iterator over an enum type
95 * It can be instantiated using any enum (or C++11 strongly-typed enum)
96 * value; the most common expected use scenario has iterators emitted by
97 * EnumRange and WholeEnum via standard rbegin() and rend() calls.
99 * In order for the iterator to work, it is mandatory that the underlying
100 * enum type's representation values be sequential.
102 * The iterator does not check for bounds; behavior is undefined if the iterator
103 * is incremented (or decremented) outside the range representing valid
104 * enum symbols (remember: an enum is not a data structure).
106 * \see EnumRange, WholeEnum, EnumIterator
108 template <typename EnumType
>
109 class ReverseEnumIterator
: public EnumIteratorBase
<EnumType
>
112 explicit ReverseEnumIterator(EnumType e
) : EnumIteratorBase
<EnumType
>(e
) {}
115 ReverseEnumIterator
& operator++() {
116 -- EnumIteratorBase
<EnumType
>::current
;
121 ReverseEnumIterator
& operator++(int) {
122 ReverseEnumIterator
rv(*this);
123 -- EnumIteratorBase
<EnumType
>::current
;
128 ReverseEnumIterator
& operator--() {
129 ++ EnumIteratorBase
<EnumType
>::current
;
134 ReverseEnumIterator
& operator--(int) {
135 ReverseEnumIterator
rv(*this);
136 ++ EnumIteratorBase
<EnumType
>::current
;
141 /** Class expressing a continuous range of an enum for range-for expressions
143 * This class requires that the underlying enum values be represented by
144 * continuous values of an integral type.
145 * Users will usually not rely on this class directly but on the more convenient
148 * \note EnumIterator<enum>(EnumType::firstmember,EnumType::lastmember)
149 * will miss EnumType::lastmember while iterating. If you need to iterate
150 * over all of EnumType, use class WholeEnum.
152 * \see EnumRange, WholeEnum
154 template <typename EnumType
>
158 typedef EnumIterator
<EnumType
> iterator
;
159 typedef ReverseEnumIterator
<EnumType
> reverse_iterator
;
160 EnumRangeT(EnumType first
, EnumType one_past_last
) : begin_(first
), end_(one_past_last
) { }
161 iterator
begin() const { return iterator(begin_
);}
162 iterator
end() const { return iterator(end_
);}
163 reverse_iterator
rbegin() const { return ++reverse_iterator(end_
); }
164 reverse_iterator
rend() const { return ++reverse_iterator(begin_
); }
170 /** Generate a continuous range of an enum for range-for expressions
172 * convenience function to deduce the right type for instantiating EnumRangeT.
173 * See EnumRangeT for more detailed documentation and caveats.
177 * enum class EnumType {
178 * blue, red, yellow, green, pink
180 * for (auto enumvalue : EnumRange(EnumType::red,EnumType::green)) {
181 * do_stuff(enumvalue); // will be called twice, with arguments red and yellow
185 template <typename EnumType
>
186 EnumRangeT
<EnumType
> EnumRange(EnumType begin
, EnumType one_past_end
)
188 return EnumRangeT
<EnumType
>(begin
,one_past_end
);
191 /** Class expressing a continuous range of a whole enum for range-for expressions
193 * Class for iterating all enum values, from EnumType::enumBegin_ up to, but
194 * not including, EnumType::enumEnd_.
196 * This class requires that:
197 * - the underlying enum values be represented by continuous values of
199 * - both enumBegin_ and enumEnd_ markers must be present as EnumType values;
200 * - enumBegin_ must have the same representation as the first element of the
202 * - enumEnd_ must have a representation that is one past the last
203 * user-accessible value of the enum.
207 * enum class EnumType {
209 * first_value = enumBegin_,
213 * for(auto enumvalue : WholeEnum<EnumType>()) {
218 template <typename EnumType
>
219 class WholeEnum
: public EnumRangeT
<EnumType
>
222 WholeEnum() : EnumRangeT
<EnumType
>(EnumType::enumBegin_
, EnumType::enumEnd_
) {}
225 #endif /* SQUID_BASE_ENUMITERATOR_H */