OR-Tools  9.6
graph/iterators.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <iterator>
20 #include <vector>
21 
22 namespace util {
23 
24 // This is useful for wrapping iterators of a class that support many different
25 // iterations. For instance, on a Graph class, one can write:
26 //
27 // BeginEndWrapper<OutgoingArcIterator> Graph::OutgoingArcs(NodeInde node)
28 // const {
29 // return BeginEndWrapper(
30 // OutgoingArcIterator(*this, node, /*at_end=*/false),
31 // OutgoingArcIterator(*this, node, /*at_end=*/true));
32 // }
33 //
34 // And a client will use it like this:
35 //
36 // for (const ArcIndex arc : graph.OutgoingArcs(node)) { ... }
37 template <typename Iterator>
39  public:
40  using const_iterator = Iterator;
41  using value_type = typename std::iterator_traits<Iterator>::value_type;
42 
43  BeginEndWrapper(Iterator begin, Iterator end) : begin_(begin), end_(end) {}
44  Iterator begin() const { return begin_; }
45  Iterator end() const { return end_; }
46  size_t size() const { return end_ - begin_; }
47 
48  bool empty() const { return begin() == end(); }
49 
50  private:
51  const Iterator begin_;
52  const Iterator end_;
53 };
54 
55 // Inline wrapper methods, to make the client code even simpler.
56 // The harm of overloading is probably less than the benefit of the nice,
57 // compact name, in this special case.
58 template <typename Iterator>
59 inline BeginEndWrapper<Iterator> BeginEndRange(Iterator begin, Iterator end) {
60  return BeginEndWrapper<Iterator>(begin, end);
61 }
62 template <typename Iterator>
64  std::pair<Iterator, Iterator> begin_end) {
65  return BeginEndWrapper<Iterator>(begin_end.first, begin_end.second);
66 }
67 
68 // Shortcut for BeginEndRange(multimap::equal_range(key)).
69 // TODO(user): go further and expose only the values, not the pairs (key,
70 // values) since the caller already knows the key.
71 template <typename MultiMap>
73  MultiMap& multi_map, const typename MultiMap::key_type& key) {
74  return BeginEndRange(multi_map.equal_range(key));
75 }
76 template <typename MultiMap>
78  const MultiMap& multi_map, const typename MultiMap::key_type& key) {
79  return BeginEndRange(multi_map.equal_range(key));
80 }
81 
82 // The Reverse() function allows to reverse the iteration order of a range-based
83 // for loop over a container that support STL reverse iterators.
84 // The syntax is:
85 // for (const type& t : Reverse(container_of_t)) { ... }
86 template <typename Container>
88  public:
89  explicit BeginEndReverseIteratorWrapper(const Container& c) : c_(c) {}
90  typename Container::const_reverse_iterator begin() const {
91  return c_.rbegin();
92  }
93  typename Container::const_reverse_iterator end() const { return c_.rend(); }
94 
95  private:
96  const Container& c_;
97 };
98 template <typename Container>
101 }
102 
103 // Simple iterator on an integer range, see IntegerRange below.
104 template <typename IntegerType>
106  : public std::iterator<std::input_iterator_tag, IntegerType> {
107  public:
108  explicit IntegerRangeIterator(IntegerType value) : index_(value) {}
110  : index_(other.index_) {}
112  index_ = other.index_;
113  }
114  bool operator!=(const IntegerRangeIterator& other) const {
115  // This may seems weird, but using < instead of != avoid almost-infinite
116  // loop if one use IntegerRange<int>(1, 0) below for instance.
117  return index_ < other.index_;
118  }
119  bool operator==(const IntegerRangeIterator& other) const {
120  return index_ == other.index_;
121  }
122  IntegerType operator*() const { return index_; }
124  ++index_;
125  return *this;
126  }
128  IntegerRangeIterator previous_position(*this);
129  ++index_;
130  return previous_position;
131  }
132 
133  private:
134  IntegerType index_;
135 };
136 
137 // Allows to easily construct nice functions for range-based for loop.
138 // This can be used like this:
139 //
140 // for (const int i : IntegerRange<int>(0, 10)) { ... }
141 //
142 // But it main purpose is to be used as return value for more complex classes:
143 //
144 // for (const ArcIndex arc : graph.AllOutgoingArcs());
145 // for (const NodeIndex node : graph.AllNodes());
146 template <typename IntegerType>
147 class IntegerRange : public BeginEndWrapper<IntegerRangeIterator<IntegerType>> {
148  public:
149  IntegerRange(IntegerType begin, IntegerType end)
150  : BeginEndWrapper<IntegerRangeIterator<IntegerType>>(
151  IntegerRangeIterator<IntegerType>(begin),
152  IntegerRangeIterator<IntegerType>(end)) {}
153 };
154 
155 // Allow iterating over a vector<T> as a mutable vector<T*>.
156 template <class T>
158  explicit MutableVectorIteration(std::vector<T>* v) : v_(v) {}
159  struct Iterator {
160  explicit Iterator(typename std::vector<T>::iterator it) : it_(it) {}
161  T* operator*() { return &*it_; }
163  it_++;
164  return *this;
165  }
166  bool operator!=(const Iterator& other) const { return other.it_ != it_; }
167 
168  private:
169  typename std::vector<T>::iterator it_;
170  };
171  Iterator begin() { return Iterator(v_->begin()); }
172  Iterator end() { return Iterator(v_->end()); }
173 
174  private:
175  std::vector<T>* const v_;
176 };
177 } // namespace util
178 
179 #endif // UTIL_GRAPH_ITERATORS_H_
Container::const_reverse_iterator begin() const
BeginEndReverseIteratorWrapper(const Container &c)
Container::const_reverse_iterator end() const
Iterator begin() const
Iterator end() const
typename std::iterator_traits< Iterator >::value_type value_type
BeginEndWrapper(Iterator begin, Iterator end)
IntegerRange(IntegerType begin, IntegerType end)
IntegerType operator*() const
IntegerRangeIterator & operator=(const IntegerRangeIterator &other)
IntegerRangeIterator(IntegerType value)
IntegerRangeIterator & operator++()
IntegerRangeIterator(const IntegerRangeIterator &other)
IntegerRangeIterator operator++(int)
bool operator!=(const IntegerRangeIterator &other) const
bool operator==(const IntegerRangeIterator &other) const
int64_t value
BeginEndReverseIteratorWrapper< Container > Reverse(const Container &c)
BeginEndWrapper< Iterator > BeginEndRange(Iterator begin, Iterator end)
BeginEndWrapper< typename MultiMap::iterator > EqualRange(MultiMap &multi_map, const typename MultiMap::key_type &key)
std::optional< int64_t > end
bool operator!=(const Iterator &other) const
Iterator(typename std::vector< T >::iterator it)
MutableVectorIteration(std::vector< T > *v)