1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
5 #include "cmConfigure.h" // IWYU pragma: keep
11 namespace RangeIterators {
13 template <typename Iter, typename UnaryPredicate>
17 using iterator_category = std::bidirectional_iterator_tag;
18 using value_type = typename std::iterator_traits<Iter>::value_type;
19 using difference_type = typename std::iterator_traits<Iter>::difference_type;
20 using pointer = typename std::iterator_traits<Iter>::pointer;
21 using reference = typename std::iterator_traits<Iter>::reference;
23 FilterIterator(Iter b, Iter e, UnaryPredicate p)
28 this->SatisfyPredicate();
31 FilterIterator& operator++()
34 this->SatisfyPredicate();
38 FilterIterator& operator--()
42 } while (!this->Pred(*this->Cur));
46 bool operator==(FilterIterator const& other) const
48 return this->Cur == other.Cur;
51 bool operator!=(FilterIterator const& other) const
53 return !this->operator==(other);
56 auto operator*() const -> decltype(*std::declval<Iter>())
62 void SatisfyPredicate()
64 while (this->Cur != this->End && !this->Pred(*this->Cur)) {
74 template <typename Iter, typename UnaryFunction>
75 class TransformIterator
78 using iterator_category = std::bidirectional_iterator_tag;
80 typename std::remove_cv<typename std::remove_reference<decltype(
81 std::declval<UnaryFunction>()(*std::declval<Iter>()))>::type>::type;
82 using difference_type = typename std::iterator_traits<Iter>::difference_type;
83 using pointer = value_type const*;
84 using reference = value_type const&;
86 TransformIterator(Iter i, UnaryFunction f)
92 TransformIterator& operator++()
98 TransformIterator& operator--()
104 bool operator==(TransformIterator const& other) const
106 return this->Base == other.Base;
109 bool operator!=(TransformIterator const& other) const
111 return !this->operator==(other);
114 auto operator*() const
115 -> decltype(std::declval<UnaryFunction>()(*std::declval<Iter>()))
117 return this->Func(*this->Base);
125 } // namespace RangeIterators
127 template <typename Iter>
131 using const_iterator = Iter;
132 using value_type = typename std::iterator_traits<Iter>::value_type;
133 using difference_type = typename std::iterator_traits<Iter>::difference_type;
135 cmRange(Iter b, Iter e)
136 : Begin(std::move(b))
141 Iter begin() const { return this->Begin; }
142 Iter end() const { return this->End; }
143 bool empty() const { return this->Begin == this->End; }
145 difference_type size() const
147 return std::distance(this->Begin, this->End);
150 cmRange& advance(difference_type amount) &
152 std::advance(this->Begin, amount);
156 cmRange advance(difference_type amount) &&
158 std::advance(this->Begin, amount);
159 return std::move(*this);
162 cmRange& retreat(difference_type amount) &
164 std::advance(this->End, -amount);
168 cmRange retreat(difference_type amount) &&
170 std::advance(this->End, -amount);
171 return std::move(*this);
174 template <typename UnaryPredicate>
175 bool all_of(UnaryPredicate p) const
177 return std::all_of(this->Begin, this->End, std::ref(p));
180 template <typename UnaryPredicate>
181 bool any_of(UnaryPredicate p) const
183 return std::any_of(this->Begin, this->End, std::ref(p));
186 template <typename UnaryPredicate>
187 bool none_of(UnaryPredicate p) const
189 return std::none_of(this->Begin, this->End, std::ref(p));
192 template <typename UnaryPredicate>
193 auto filter(UnaryPredicate p) const
194 -> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>>
196 using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>;
197 return { It(this->Begin, this->End, p), It(this->End, this->End, p) };
200 template <typename UnaryFunction>
201 auto transform(UnaryFunction f) const
202 -> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>>
204 using It = RangeIterators::TransformIterator<Iter, UnaryFunction>;
205 return { It(this->Begin, f), It(this->End, f) };
213 template <typename Iter1, typename Iter2>
214 bool operator==(cmRange<Iter1> const& left, cmRange<Iter2> const& right)
216 return left.size() == right.size() &&
217 std::equal(left.begin(), left.end(), right.begin());
220 template <typename Iter1, typename Iter2>
221 auto cmMakeRange(Iter1 begin, Iter2 end) -> cmRange<Iter1>
223 return { begin, end };
226 template <typename Range>
227 auto cmMakeRange(Range const& range) -> cmRange<decltype(range.begin())>
229 return { range.begin(), range.end() };
232 template <typename Range>
233 auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())>
235 return { range.rbegin(), range.rend() };