iterators.h 6 KB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
// Copyright 2010-2018 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Helper classes to make it easy to implement range-based for loops.

#ifndef UTIL_GRAPH_ITERATORS_H_
#define UTIL_GRAPH_ITERATORS_H_

#include <iterator>
#include <vector>

namespace util {

// This is useful for wrapping iterators of a class that support many different
// iterations. For instance, on a Graph class, one can write:
//
// BeginEndWrapper<OutgoingArcIterator> Graph::OutgoingArcs(NodeInde node)
//      const {
//   return BeginEndRange(
//       OutgoingArcIterator(*this, node, /*at_end=*/false),
//       OutgoingArcIterator(*this, node, /*at_end=*/true));
// }
//
// And a client will use it like this:
//
// for (const ArcIndex arc : graph.OutgoingArcs(node)) { ... }
template <typename Iterator>
class BeginEndWrapper {
 public:
  using const_iterator = Iterator;
  using value_type = typename std::iterator_traits<Iterator>::value_type;

  BeginEndWrapper(Iterator begin, Iterator end) : begin_(begin), end_(end) {}
  Iterator begin() const { return begin_; }
  Iterator end() const { return end_; }

  bool empty() const { return begin() == end(); }

 private:
  const Iterator begin_;
  const Iterator end_;
};

// Inline wrapper methods, to make the client code even simpler.
// The harm of overloading is probably less than the benefit of the nice,
// compact name, in this special case.
template <typename Iterator>
inline BeginEndWrapper<Iterator> BeginEndRange(Iterator begin, Iterator end) {
  return BeginEndWrapper<Iterator>(begin, end);
}
template <typename Iterator>
inline BeginEndWrapper<Iterator> BeginEndRange(
    std::pair<Iterator, Iterator> begin_end) {
  return BeginEndWrapper<Iterator>(begin_end.first, begin_end.second);
}

// Shortcut for BeginEndRange(multimap::equal_range(key)).
// TODO(user): go further and expose only the values, not the pairs (key,
// values) since the caller already knows the key.
template <typename MultiMap>
inline BeginEndWrapper<typename MultiMap::iterator> EqualRange(
    MultiMap& multi_map, const typename MultiMap::key_type& key) {
  return BeginEndRange(multi_map.equal_range(key));
}
template <typename MultiMap>
inline BeginEndWrapper<typename MultiMap::const_iterator> EqualRange(
    const MultiMap& multi_map, const typename MultiMap::key_type& key) {
  return BeginEndRange(multi_map.equal_range(key));
}

// The Reverse() function allows to reverse the iteration order of a range-based
// for loop over a container that support STL reverse iterators.
// The syntax is:
//   for (const type& t : Reverse(container_of_t)) { ... }
template <typename Container>
class BeginEndReverseIteratorWrapper {
 public:
  explicit BeginEndReverseIteratorWrapper(const Container& c) : c_(c) {}
  typename Container::const_reverse_iterator begin() const {
    return c_.rbegin();
  }
  typename Container::const_reverse_iterator end() const { return c_.rend(); }

 private:
  const Container& c_;
};
template <typename Container>
BeginEndReverseIteratorWrapper<Container> Reverse(const Container& c) {
  return BeginEndReverseIteratorWrapper<Container>(c);
}

// Simple iterator on an integer range, see IntegerRange below.
template <typename IntegerType>
class IntegerRangeIterator
    : public std::iterator<std::input_iterator_tag, IntegerType> {
 public:
  explicit IntegerRangeIterator(IntegerType value) : index_(value) {}
  IntegerRangeIterator(const IntegerRangeIterator& other)
      : index_(other.index_) {}
  IntegerRangeIterator& operator=(const IntegerRangeIterator& other) {
    index_ = other.index_;
  }
  bool operator!=(const IntegerRangeIterator& other) const {
    // This may seems weird, but using < instead of != avoid almost-infinite
    // loop if one use IntegerRange<int>(1, 0) below for instance.
    return index_ < other.index_;
  }
  bool operator==(const IntegerRangeIterator& other) const {
    return index_ == other.index_;
  }
  IntegerType operator*() const { return index_; }
  IntegerRangeIterator& operator++() {
    ++index_;
    return *this;
  }
  IntegerRangeIterator operator++(int) {
    IntegerRangeIterator previous_position(*this);
    ++index_;
    return previous_position;
  }

 private:
  IntegerType index_;
};

// Allows to easily construct nice functions for range-based for loop.
// This can be used like this:
//
// for (const int i : IntegerRange<int>(0, 10)) { ... }
//
// But it main purpose is to be used as return value for more complex classes:
//
// for (const ArcIndex arc : graph.AllOutgoingArcs());
// for (const NodeIndex node : graph.AllNodes());
template <typename IntegerType>
class IntegerRange : public BeginEndWrapper<IntegerRangeIterator<IntegerType>> {
 public:
  IntegerRange(IntegerType begin, IntegerType end)
      : BeginEndWrapper<IntegerRangeIterator<IntegerType>>(
            IntegerRangeIterator<IntegerType>(begin),
            IntegerRangeIterator<IntegerType>(end)) {}
};

// Allow iterating over a vector<T> as a mutable vector<T*>.
template <class T>
struct MutableVectorIteration {
  explicit MutableVectorIteration(std::vector<T>* v) : v_(v) {}
  struct Iterator {
    explicit Iterator(typename std::vector<T>::iterator it) : it_(it) {}
    T* operator*() { return &*it_; }
    Iterator& operator++() {
      it_++;
      return *this;
    }
    bool operator!=(const Iterator& other) const { return other.it_ != it_; }

   private:
    typename std::vector<T>::iterator it_;
  };
  Iterator begin() { return Iterator(v_->begin()); }
  Iterator end() { return Iterator(v_->end()); }

 private:
  std::vector<T>* const v_;
};
}  // namespace util

#endif  // UTIL_GRAPH_ITERATORS_H_