OR-Tools  9.6
math_opt/storage/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 #ifndef OR_TOOLS_MATH_OPT_STORAGE_ITERATORS_H_
15 #define OR_TOOLS_MATH_OPT_STORAGE_ITERATORS_H_
16 
17 #include <iterator>
18 
20 
22 
23 // An iterator for iterating over a field of the update trackers stored by
24 // ModelStorage. Typically create with MakeUpdateDataFieldIterator() below to
25 // avoid manually giving all type parameters, or better, with
26 // MakeUpdateDataFieldRange().
27 //
28 // Sample use:
29 // const std::vector<std::pair<
30 // UpdateTrackerId, std::unique_ptr<UpdateTrackerData>>>& data = ...;
31 // for(LinearConstraintStorage::Diff& diff :
32 // MakeUpdateDataFieldRange<
33 // &UpdateTrackerData::dirty_linear_constraints>(data)) {
34 // ...
35 // }
36 //
37 // BaseIter must iterate over
38 // const std::pair<XXX, std::unique_ptr<UpdateData>>&
39 // The returned iterator will be over non-const references to Field as read off
40 // the UpdateData values.
41 template <typename UpdateData, typename V, V UpdateData::*Field,
42  typename BaseIter>
44  public:
45  using value_type = V;
46  using reference = V&;
47  using pointer = V*;
48  using difference_type = typename BaseIter::difference_type;
49  using iterator_category = std::forward_iterator_tag;
50 
51  explicit UpdateDataFieldIterator(BaseIter base_iter)
52  : base_iter_(std::move(base_iter)) {}
53 
54  reference operator*() const { return base_iter_->second.get()->*Field; }
55  pointer operator->() const { return &base_iter_->second->*Field; }
56  // Prefix
58  ++base_iter_;
59  return *this;
60  }
61  // Postfix
63  UpdateDataFieldIterator result = *this;
64  ++base_iter_;
65  return result;
66  }
67 
68  friend bool operator==(const UpdateDataFieldIterator& lhs,
69  const UpdateDataFieldIterator& rhs) {
70  return lhs.base_iter_ == rhs.base_iter_;
71  }
72  friend bool operator!=(const UpdateDataFieldIterator& lhs,
73  const UpdateDataFieldIterator& rhs) {
74  return lhs.base_iter_ != rhs.base_iter_;
75  }
76 
77  private:
78  BaseIter base_iter_;
79 };
80 
81 // The "functions" are used to extract the types of the field and of the class
82 // from pointers-to-member. They have no implementation since they are only used
83 // with `decltype`.
84 //
85 // Example:
86 // int A::* ptr = &A::x;
87 // decltype(MemberPointerValueType(PointerToMember)) v;
88 // decltype(MemberPointerClassType(PointerToMember)) c;
89 // // The type of `v` is `int` and the type of `c` is `A`.
90 template <typename V, typename C>
92 template <typename V, typename C>
94 
95 // Returns a new iterator on the field identified by the PointerToMember
96 // wrapping an iterator of a:
97 // std::vector<std::pair<ID, std::unique_ptr<UpdateData>>
98 //
99 // Example:
100 // std::vector<std::pair<Id, std::unique_ptr<UpdateData>> update_trackers;
101 // const auto begin =
102 // MakeUpdateDataFieldIterator<&UpdateData::field>(update_trackers.cbegin());
103 template <auto PointerToMember, typename BaseIter>
104 auto MakeUpdateDataFieldIterator(BaseIter base_iter) {
106  decltype(MemberPointerClassType(PointerToMember)),
107  decltype(MemberPointerValueType(PointerToMember)), PointerToMember,
108  BaseIter>(std::move(base_iter));
109 }
110 
111 // Returns a range (begin and end iterator) pointing to the field identified by
112 // the PointerToMember from an iterable of
113 // std::pair<ID, std::unique_ptr<UpdateData>
114 //
115 // Example:
116 // std::vector<std::pair<Id, std::unique_ptr<UpdateData>> trackers;
117 // for(auto& f : MakeUpdateDataFieldRange<&UpdateData::field>(trackers)) {
118 // ...
119 // }
120 template <auto PointerToMember, typename UpdateTrackers>
122  return make_range(
123  MakeUpdateDataFieldIterator<PointerToMember>(trackers.begin()),
124  MakeUpdateDataFieldIterator<PointerToMember>(trackers.end()));
125 }
126 
127 } // namespace operations_research::math_opt
128 
129 #endif // OR_TOOLS_MATH_OPT_STORAGE_ITERATORS_H_
friend bool operator==(const UpdateDataFieldIterator &lhs, const UpdateDataFieldIterator &rhs)
friend bool operator!=(const UpdateDataFieldIterator &lhs, const UpdateDataFieldIterator &rhs)
auto MakeUpdateDataFieldIterator(BaseIter base_iter)
iterator_range< T > make_range(T x, T y)
Definition: range.h:70
auto MakeUpdateDataFieldRange(const UpdateTrackers &trackers)