GeneralIndexIterator.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <type_traits>
7 #include <vector>
8 
9 #include "Utilities/Gsl.hpp"
10 
11 /// Iterate over a generic "block" of coordinates. The constructor
12 /// takes a container of pairs defining the range (inclusive start,
13 /// exclusive end) of each coordinate. The utility function
14 /// make_general_index_iterator() is provided for easier construction.
15 template <typename Container>
17  public:
18  using value_type = typename Container::value_type::first_type;
19  using iterator_type = typename std::vector<value_type>::const_iterator;
20 
21  explicit GeneralIndexIterator(Container ranges) noexcept
22  : ranges_(std::move(ranges)) {
23  current_.reserve(ranges_.size());
24  for (const auto& range : ranges_) {
25  if (range.first == range.second) {
26  done_ = true;
27  return;
28  }
29  current_.push_back(range.first);
30  }
31  }
32 
33  /// Access the given coordinate of the current value.
34  const value_type& operator[](size_t i) const noexcept { return current_[i]; }
35 
36  /// Check whether the iterator is complete. Calling any of the
37  /// other methods on a completed iterator is undefined behavior.
38  explicit operator bool() const noexcept { return not done_; }
39 
40  void operator++() noexcept {
41  for (size_t index = 0; index < current_.size(); ++index) {
42  ++current_[index];
43  if (current_[index] != gsl::at(ranges_, index).second) { return; }
44  current_[index] = gsl::at(ranges_, index).first;
45  }
46  done_ = true;
47  }
48 
49  /// Iterate over the coordinates of the current value.
50  //@{
51  iterator_type cbegin() const noexcept { return current_.cbegin(); }
52  iterator_type cend() const noexcept { return current_.cend(); }
53  iterator_type begin() const noexcept { return cbegin(); }
54  iterator_type end() const noexcept { return cend(); }
55  //@}
56 
57  private:
58  Container ranges_;
59  std::vector<value_type> current_{};
60  bool done_{false};
61 };
62 
63 /// Construct a GeneralIndexIterator
64 template <typename Container>
65 GeneralIndexIterator<std::decay_t<Container>> make_general_index_iterator(
66  Container&& ranges) noexcept {
68  std::forward<Container>(ranges));
69 }
Iterate over a generic "block" of coordinates. The constructor takes a container of pairs defining th...
Definition: GeneralIndexIterator.hpp:16
iterator_type cend() const noexcept
Iterate over the coordinates of the current value.
Definition: GeneralIndexIterator.hpp:52
const value_type & operator[](size_t i) const noexcept
Access the given coordinate of the current value.
Definition: GeneralIndexIterator.hpp:34
iterator_type cbegin() const noexcept
Iterate over the coordinates of the current value.
Definition: GeneralIndexIterator.hpp:51
Defines functions and classes from the GSL.
iterator_type end() const noexcept
Iterate over the coordinates of the current value.
Definition: GeneralIndexIterator.hpp:54
iterator_type begin() const noexcept
Iterate over the coordinates of the current value.
Definition: GeneralIndexIterator.hpp:53
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid...
Definition: Gsl.hpp:124