Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
iterators.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// Helper classes to make it easy to implement range-based for loops.
15
16#ifndef UTIL_GRAPH_ITERATORS_H_
17#define UTIL_GRAPH_ITERATORS_H_
18
19#include <cstddef>
20#include <iterator>
21#include <utility>
22
23#include "absl/log/check.h"
24
25namespace util {
26
27// This is useful for wrapping iterators of a class that support many different
28// iterations. For instance, on a Graph class, one can write:
29//
30// BeginEndWrapper<OutgoingArcIterator> Graph::OutgoingArcs(NodeInde node)
31// const {
32// return BeginEndWrapper(
33// OutgoingArcIterator(*this, node, /*at_end=*/false),
34// OutgoingArcIterator(*this, node, /*at_end=*/true));
35// }
36//
37// And a client will use it like this:
38//
39// for (const ArcIndex arc : graph.OutgoingArcs(node)) { ... }
40//
41// Note that `BeginEndWrapper` is conceptually a borrowed range as per the C++
42// standard (`std::ranges::borrowed_range`):
43// "The concept borrowed_range defines the requirements of a range such that a
44// function can take it by value and return iterators obtained from it without
45// danger of dangling". We cannot `static_assert` this property though as
46// `std::ranges` is prohibited in google3.
47template <typename Iterator>
49 public:
50 using const_iterator = Iterator;
51 using value_type = typename std::iterator_traits<Iterator>::value_type;
52
53 // If `Iterator` is default-constructible, an empty range.
54 BeginEndWrapper() = default;
55
56 BeginEndWrapper(Iterator begin, Iterator end) : begin_(begin), end_(end) {}
57
58 Iterator begin() const { return begin_; }
59 Iterator end() const { return end_; }
60
61 // Available only if `Iterator` is a random access iterator.
62 size_t size() const { return end_ - begin_; }
63
64 bool empty() const { return begin() == end(); }
65
66 private:
67 Iterator begin_;
68 Iterator end_;
69};
70
71// Inline wrapper methods, to make the client code even simpler.
72// The harm of overloading is probably less than the benefit of the nice,
73// compact name, in this special case.
74template <typename Iterator>
75inline BeginEndWrapper<Iterator> BeginEndRange(Iterator begin, Iterator end) {
76 return BeginEndWrapper<Iterator>(begin, end);
77}
78template <typename Iterator>
80 std::pair<Iterator, Iterator> begin_end) {
81 return BeginEndWrapper<Iterator>(begin_end.first, begin_end.second);
82}
83
84// Shortcut for BeginEndRange(multimap::equal_range(key)).
85// TODO(user): go further and expose only the values, not the pairs (key,
86// values) since the caller already knows the key.
87template <typename MultiMap>
89 MultiMap& multi_map, const typename MultiMap::key_type& key) {
90 return BeginEndRange(multi_map.equal_range(key));
91}
92template <typename MultiMap>
94 const MultiMap& multi_map, const typename MultiMap::key_type& key) {
95 return BeginEndRange(multi_map.equal_range(key));
96}
97
98// The Reverse() function allows to reverse the iteration order of a range-based
99// for loop over a container that support STL reverse iterators.
100// The syntax is:
101// for (const type& t : Reverse(container_of_t)) { ... }
102template <typename Container>
104 public:
105 explicit BeginEndReverseIteratorWrapper(const Container& c) : c_(c) {}
106 typename Container::const_reverse_iterator begin() const {
107 return c_.rbegin();
108 }
109 typename Container::const_reverse_iterator end() const { return c_.rend(); }
110
111 private:
112 const Container& c_;
113};
114template <typename Container>
118
119// Simple iterator on an integer range, see `IntegerRange` below.
120// `IntegerType` can be any signed integer type, or strong integer type that
121// defines usual operations (e.g. `gtl::IntType<T>`).
122template <typename IntegerType>
124// TODO(b/385094969): In C++17, `std::iterator_traits<Iterator>` required
125// explicitly specifying the iterator category. Remove this when backwards
126// compatibility with C++17 is no longer needed.
127#if __cplusplus < 201703L
128 : public std::iterator<std::input_iterator_tag, IntegerType>
129#endif
130{
131 public:
132 using difference_type = ptrdiff_t;
133 using value_type = IntegerType;
134#if __cplusplus >= 201703L && __cplusplus < 202002L
135 using iterator_category = std::input_iterator_tag;
136 using pointer = IntegerType*;
137 using reference = IntegerType&;
138#endif
139
140 IntegerRangeIterator() : index_{} {}
141
142 explicit IntegerRangeIterator(IntegerType value) : index_(value) {}
143
144 IntegerType operator*() const { return index_; }
145
146 // TODO(b/385094969): Use `=default` when backwards compatibility with C++17
147 // is no longer needed.
148 bool operator==(const IntegerRangeIterator& other) const {
149 return index_ == other.index_;
150 }
151 bool operator!=(const IntegerRangeIterator& other) const {
152 return index_ != other.index_;
153 }
154 bool operator<(const IntegerRangeIterator& other) const {
155 return index_ < other.index_;
156 }
157 bool operator>(const IntegerRangeIterator& other) const {
158 return index_ > other.index_;
159 }
160 bool operator<=(const IntegerRangeIterator& other) const {
161 return index_ <= other.index_;
162 }
163 bool operator>=(const IntegerRangeIterator& other) const {
164 return index_ >= other.index_;
165 }
166
168 ++index_;
169 return *this;
170 }
171
173 auto tmp = *this;
174 ++*this;
175 return tmp;
176 }
177
179 index_ += n;
180 return *this;
181 }
182
184 --index_;
185 return *this;
186 }
187
189 auto tmp = *this;
190 --*this;
191 return tmp;
192 }
193
195 index_ -= n;
196 return *this;
197 }
198
199 IntegerType operator[](difference_type n) const { return index_ + n; }
200
202 difference_type n) {
203 return IntegerRangeIterator(it.index_ + n);
204 }
205
208 return IntegerRangeIterator(it.index_ + n);
209 }
210
212 difference_type n) {
213 return IntegerRangeIterator(it.index_ - n);
214 }
215
217 const IntegerRangeIterator r) {
218 return static_cast<difference_type>(l.index_ - r.index_);
219 }
220
221 private:
222 IntegerType index_;
223};
224
225// Allows to easily construct nice functions for range-based for loop.
226// This can be used like this:
227//
228// for (const int i : IntegerRange<int>(0, 10)) { ... }
229//
230// But it main purpose is to be used as return value for more complex classes:
231//
232// for (const ArcIndex arc : graph.AllOutgoingArcs());
233// for (const NodeIndex node : graph.AllNodes());
234template <typename IntegerType>
235class IntegerRange : public BeginEndWrapper<IntegerRangeIterator<IntegerType>> {
236 public:
237 // Requires `begin <= end`.
238 IntegerRange(IntegerType begin, IntegerType end)
240 IntegerRangeIterator<IntegerType>(begin),
241 IntegerRangeIterator<IntegerType>(end)) {
242 DCHECK_LE(begin, end);
243 }
244};
245
246// A helper class for implementing list graph iterators: This does pointer
247// chasing on `next` until `sentinel` is found. `Tag` allows distinguishing
248// different iterators with the same index type and sentinel.
249template <typename IndexT, const IndexT& sentinel, typename Tag>
251#if __cplusplus < 201703L
252 : public std::iterator<std::input_iterator_tag, IndexT>
253#endif
254{
255 public:
256 using difference_type = ptrdiff_t;
257 using value_type = IndexT;
258#if __cplusplus >= 201703L && __cplusplus < 202002L
259 using iterator_category = std::input_iterator_tag;
260 using pointer = IndexT*;
261 using reference = IndexT&;
262#endif
263
264 ChasingIterator() : index_(sentinel), next_(nullptr) {}
265
266 ChasingIterator(IndexT index, const IndexT* next)
267 : index_(index), next_(next) {}
268
269 IndexT operator*() const { return index_; }
270
272 index_ = next_[static_cast<ptrdiff_t>(index_)];
273 return *this;
274 }
276 auto tmp = *this;
277 index_ = next_[static_cast<ptrdiff_t>(index_)];
278 return tmp;
279 }
280
281 friend bool operator==(const ChasingIterator& l, const ChasingIterator& r) {
282 return l.index_ == r.index_;
283 }
284 friend bool operator!=(const ChasingIterator& l, const ChasingIterator& r) {
285 return l.index_ != r.index_;
286 }
287
288 private:
289 IndexT index_;
290 const IndexT* next_;
291};
292
293} // namespace util
294
295#endif // UTIL_GRAPH_ITERATORS_H_
BeginEndReverseIteratorWrapper(const Container &c)
Definition iterators.h:105
Container::const_reverse_iterator end() const
Definition iterators.h:109
Container::const_reverse_iterator begin() const
Definition iterators.h:106
Iterator end() const
Definition iterators.h:59
Iterator begin() const
Definition iterators.h:58
BeginEndWrapper(Iterator begin, Iterator end)
Definition iterators.h:56
bool empty() const
Definition iterators.h:64
BeginEndWrapper()=default
If Iterator is default-constructible, an empty range.
typename std::iterator_traits< Iterator >::value_type value_type
Definition iterators.h:51
Iterator const_iterator
Definition iterators.h:50
size_t size() const
Available only if Iterator is a random access iterator.
Definition iterators.h:62
ChasingIterator(IndexT index, const IndexT *next)
Definition iterators.h:266
friend bool operator!=(const ChasingIterator &l, const ChasingIterator &r)
Definition iterators.h:284
IndexT operator*() const
Definition iterators.h:269
ChasingIterator operator++(int)
Definition iterators.h:275
friend bool operator==(const ChasingIterator &l, const ChasingIterator &r)
Definition iterators.h:281
ChasingIterator & operator++()
Definition iterators.h:271
friend IntegerRangeIterator operator+(IntegerRangeIterator it, difference_type n)
Definition iterators.h:201
bool operator<(const IntegerRangeIterator &other) const
Definition iterators.h:154
bool operator==(const IntegerRangeIterator &other) const
Definition iterators.h:148
friend IntegerRangeIterator operator+(difference_type n, IntegerRangeIterator it)
Definition iterators.h:206
IntegerRangeIterator operator--(int)
Definition iterators.h:188
IntegerRangeIterator & operator--()
Definition iterators.h:183
IntegerRangeIterator & operator+=(difference_type n)
Definition iterators.h:178
IntegerRangeIterator & operator++()
Definition iterators.h:167
bool operator!=(const IntegerRangeIterator &other) const
Definition iterators.h:151
bool operator>=(const IntegerRangeIterator &other) const
Definition iterators.h:163
bool operator>(const IntegerRangeIterator &other) const
Definition iterators.h:157
IntegerRangeIterator(IntegerType value)
Definition iterators.h:142
bool operator<=(const IntegerRangeIterator &other) const
Definition iterators.h:160
IntegerType operator*() const
Definition iterators.h:144
friend difference_type operator-(const IntegerRangeIterator l, const IntegerRangeIterator r)
Definition iterators.h:216
IntegerRangeIterator & operator-=(difference_type n)
Definition iterators.h:194
IntegerType operator[](difference_type n) const
Definition iterators.h:199
friend IntegerRangeIterator operator-(IntegerRangeIterator it, difference_type n)
Definition iterators.h:211
IntegerRangeIterator operator++(int)
Definition iterators.h:172
IntegerRange(IntegerType begin, IntegerType end)
Requires begin <= end.
Definition iterators.h:238
A collections of i/o utilities for the Graph classes in ./graph.h.
BeginEndReverseIteratorWrapper< Container > Reverse(const Container &c)
Definition iterators.h:115
BeginEndWrapper< Iterator > BeginEndRange(Iterator begin, Iterator end)
Definition iterators.h:75
BeginEndWrapper< typename MultiMap::iterator > EqualRange(MultiMap &multi_map, const typename MultiMap::key_type &key)
Definition iterators.h:88
if(!yyg->yy_init)
Definition parser.yy.cc:966