swift
iterator.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_ITERATOR_H
7 #define SWIFT_MISC_ITERATOR_H
8 
9 #include <algorithm>
10 #include <iterator>
11 #include <type_traits>
12 #include <utility>
13 
14 #include "misc/optional.h"
15 #include "misc/typetraits.h"
16 
18 {
22  template <class F>
24  {
25  public:
28  using iterator_category = std::output_iterator_tag;
29  using value_type = void;
30  using difference_type = void;
31  using pointer = void;
32  using reference = void;
34 
37  explicit OutputIterator(const F &func) : m_func(func) {}
38  explicit OutputIterator(F &&func) : m_func(std::move(func)) {}
39  OutputIterator(const OutputIterator &other) : m_func(other.m_func) {}
41 
44  OutputIterator &operator++() { return *this; }
45  OutputIterator operator++(int) { return *this; }
47 
49  OutputIterator &operator*() { return *this; }
50 
52  template <typename T, std::enable_if_t<!std::is_convertible_v<T, OutputIterator>, int> = 0>
54  {
55  m_func(std::forward<T>(value));
56  return *this;
57  }
58 
61  {
62  // Work around lambda's deleted copy assignment operator
63  this->~OutputIterator();
64  new (this) OutputIterator(other);
65  return *this;
66  }
67 
69  ~OutputIterator() = default;
70 
71  private:
72  F m_func;
73  };
74 
78  template <class F>
79  auto makeOutputIterator(F &&func)
80  {
81  return OutputIterator<std::decay_t<F>>(std::forward<F>(func));
82  }
83 
87  template <class T>
88  auto makeInsertIterator(T &container)
89  {
90  if constexpr (THasPushBack<T>::value)
91  {
92  return makeOutputIterator([&container](auto &&v) { container.push_back(std::forward<decltype(v)>(v)); });
93  }
94  else
95  {
96  return makeOutputIterator([&container](auto &&v) { container.insert(std::forward<decltype(v)>(v)); });
97  }
98  }
99 
106  template <class I, class F>
108  {
109  public:
112  using iterator_category = std::forward_iterator_tag;
113  using value_type =
114  std::decay_t<decltype(std::declval<F>()(std::declval<typename std::iterator_traits<I>::value_type>()))>;
115  using difference_type = typename std::iterator_traits<I>::difference_type;
116  using reference = typename std::iterator_traits<I>::reference;
118 
121  decltype(std::declval<F>()(std::declval<typename std::iterator_traits<I>::value_type>()));
122 
125  struct PointerWrapper
126  {
127  PointerWrapper(std::decay_t<undecayed_type> *obj) : m_obj(std::move(*obj)) {}
128  std::decay_t<undecayed_type> const *operator->() const { return &m_obj; }
129  std::decay_t<undecayed_type> operator*() const & { return m_obj; }
130  std::decay_t<undecayed_type> operator*() && { return std::move(m_obj); }
131 
132  private:
133  const std::decay_t<undecayed_type> m_obj;
134  };
135 
137  using pointer = typename std::conditional<std::is_reference_v<undecayed_type>,
138  std::remove_reference_t<undecayed_type> *, PointerWrapper>::type;
139 
141  TransformIterator(I iterator, F function) : m_iterator(iterator), m_function(function) {}
142 
144  TransformIterator(I end) : m_iterator(end) {}
145 
150  {
151  ++m_iterator;
152  return *this;
153  }
155  {
156  auto copy = *this;
157  ++m_iterator;
158  return copy;
159  }
161 
165  {
166  Q_ASSERT(m_function);
167  return (*m_function)(*m_iterator);
168  }
169 
174  {
175  Q_ASSERT(m_function);
176  auto &&obj = (*m_function)(*m_iterator);
177  return &obj;
178  }
179 
182  bool operator==(const TransformIterator &other) const { return m_iterator == other.m_iterator; }
183  bool operator!=(const TransformIterator &other) const { return m_iterator != other.m_iterator; }
184  bool operator<(const TransformIterator &other) const { return m_iterator < other.m_iterator; }
185  bool operator<=(const TransformIterator &other) const { return m_iterator <= other.m_iterator; }
186  bool operator>(const TransformIterator &other) const { return m_iterator > other.m_iterator; }
187  bool operator>=(const TransformIterator &other) const { return m_iterator >= other.m_iterator; }
189 
190  private:
191  I m_iterator;
192  Optional<F> m_function;
193  };
194 
201  template <class I, class F>
203  {
204  public:
207  using iterator_category = std::forward_iterator_tag;
208  using value_type = typename std::iterator_traits<I>::value_type;
209  using difference_type = typename std::iterator_traits<I>::difference_type;
210  using pointer = typename std::iterator_traits<I>::pointer;
211  using reference = typename std::iterator_traits<I>::reference;
213 
215  ConditionalIterator(I iterator, I end, F predicate) : m_iterator(iterator), m_end(end), m_predicate(predicate)
216  {
217  while (m_iterator != m_end && !(*m_predicate)(*m_iterator)) { ++m_iterator; }
218  }
219 
221  ConditionalIterator(I end) : m_iterator(end), m_end(end) {}
222 
227  {
228  Q_ASSERT(m_predicate);
229  do {
230  ++m_iterator;
231  }
232  while (m_iterator != m_end && !(*m_predicate)(*m_iterator));
233  return *this;
234  }
236  {
237  auto copy = *this;
238  ++(*this);
239  return copy;
240  }
242 
245  I operator->() { return m_iterator; }
246 
249  typename std::iterator_traits<I>::reference operator*() { return *m_iterator; }
250 
253  bool operator==(const ConditionalIterator &other) const { return m_iterator == other.m_iterator; }
254  bool operator!=(const ConditionalIterator &other) const { return m_iterator != other.m_iterator; }
255  bool operator<(const ConditionalIterator &other) const { return m_iterator < other.m_iterator; }
256  bool operator<=(const ConditionalIterator &other) const { return m_iterator <= other.m_iterator; }
257  bool operator>(const ConditionalIterator &other) const { return m_iterator > other.m_iterator; }
258  bool operator>=(const ConditionalIterator &other) const { return m_iterator >= other.m_iterator; }
260 
262  void checkEnd(const ConditionalIterator &other) // debugging
263  {
264  Q_ASSERT(m_end == other.m_end && m_end == other.m_iterator);
265  Q_UNUSED(other);
266  }
267 
268  private:
269  I m_iterator;
270  I m_end;
271  Optional<F> m_predicate;
272  };
273 
277  template <class I>
279  {
280  public:
283  using iterator_category = std::forward_iterator_tag;
284  using value_type = typename std::iterator_traits<I>::value_type;
285  using difference_type = typename std::iterator_traits<I>::difference_type;
286  using pointer = typename std::iterator_traits<I>::pointer;
287  using reference = typename std::iterator_traits<I>::reference;
289 
291  ConcatIterator(QVector<I> iterators) : m_iterators(std::move(iterators))
292  {
293  Q_ASSERT(m_iterators.size() % 2 == 0);
294  while (!m_iterators.empty() && m_iterators[0] == m_iterators[1]) { m_iterators.remove(0, 2); }
295  }
296 
298  ConcatIterator(I end) { Q_UNUSED(end); }
299 
304  {
305  ++(m_iterators[0]);
306  while (!m_iterators.empty() && m_iterators[0] == m_iterators[1]) { m_iterators.remove(0, 2); }
307  return *this;
308  }
310  {
311  auto copy = *this;
312  ++(*this);
313  return copy;
314  }
316 
319  I operator->() { return m_iterators[0]; }
320 
323  typename std::iterator_traits<I>::reference operator*() { return *(m_iterators[0]); }
324 
327  bool operator==(const ConcatIterator &other) const { return m_iterators == other.m_iterators; }
328  bool operator!=(const ConcatIterator &other) const { return m_iterators != other.m_iterators; }
329  bool operator<(const ConcatIterator &other) const { return m_iterators < other.m_iterators; }
330  bool operator<=(const ConcatIterator &other) const { return m_iterators <= other.m_iterators; }
331  bool operator>(const ConcatIterator &other) const { return m_iterators > other.m_iterators; }
332  bool operator>=(const ConcatIterator &other) const { return m_iterators >= other.m_iterators; }
334 
335  private:
336  QVector<I> m_iterators;
337  };
338 
342  template <class I, class F>
343  auto makeTransformIterator(I iterator, F function) -> TransformIterator<I, F>
344  {
345  return { iterator, function };
346  }
347 
351  template <class I, class F>
352  auto makeConditionalIterator(I iterator, I end, F predicate) -> ConditionalIterator<I, F>
353  {
354  return { iterator, end, predicate };
355  }
356 
360  template <class I>
361  auto makeConcatIterator(QVector<I> iterators) -> ConcatIterator<I>
362  {
363  return { std::move(iterators) };
364  }
365 
366 } // namespace swift::misc::Iterators
367 
368 #endif // SWIFT_MISC_ITERATOR_H
Iterator wrapper which concatenates zero or more pairs of begin and end iterators.
Definition: iterator.h:279
ConcatIterator(I end)
Implicit conversion from an end iterator.
Definition: iterator.h:298
typename std::iterator_traits< I >::difference_type difference_type
Types.
Definition: iterator.h:285
typename std::iterator_traits< I >::value_type value_type
Types.
Definition: iterator.h:284
bool operator<=(const ConcatIterator &other) const
Comparison operators.
Definition: iterator.h:330
bool operator>=(const ConcatIterator &other) const
Comparison operators.
Definition: iterator.h:332
typename std::iterator_traits< I >::pointer pointer
Types.
Definition: iterator.h:286
bool operator!=(const ConcatIterator &other) const
Comparison operators.
Definition: iterator.h:328
bool operator<(const ConcatIterator &other) const
Comparison operators.
Definition: iterator.h:329
ConcatIterator(QVector< I > iterators)
Constructor.
Definition: iterator.h:291
std::forward_iterator_tag iterator_category
Types.
Definition: iterator.h:283
std::iterator_traits< I >::reference operator*()
Dereference operator, returns the object referenced by the iterator. Undefined if iterator is at the ...
Definition: iterator.h:323
ConcatIterator & operator++()
Advance to the next element. Undefined if iterator is at the end.
Definition: iterator.h:303
typename std::iterator_traits< I >::reference reference
Types.
Definition: iterator.h:287
I operator->()
Indirection operator, returns the underlying iterator. Undefined if iterator is at the end.
Definition: iterator.h:319
bool operator>(const ConcatIterator &other) const
Comparison operators.
Definition: iterator.h:331
ConcatIterator operator++(int)
Advance to the next element. Undefined if iterator is at the end.
Definition: iterator.h:309
bool operator==(const ConcatIterator &other) const
Comparison operators.
Definition: iterator.h:327
Iterator wrapper which skips over any elements which do not satisfy a given condition predicate.
Definition: iterator.h:203
ConditionalIterator operator++(int)
Advance the iterator to the next element which matches the predicate, or the end if there are none re...
Definition: iterator.h:235
ConditionalIterator & operator++()
Advance the iterator to the next element which matches the predicate, or the end if there are none re...
Definition: iterator.h:226
ConditionalIterator(I end)
Implicit conversion from an end iterator.
Definition: iterator.h:221
typename std::iterator_traits< I >::difference_type difference_type
Types.
Definition: iterator.h:209
typename std::iterator_traits< I >::pointer pointer
Types.
Definition: iterator.h:210
typename std::iterator_traits< I >::reference reference
Types.
Definition: iterator.h:211
typename std::iterator_traits< I >::value_type value_type
Types.
Definition: iterator.h:208
std::iterator_traits< I >::reference operator*()
Dereference operator, returns the object referenced by the iterator. Undefined if iterator is at the ...
Definition: iterator.h:249
bool operator>(const ConditionalIterator &other) const
Comparison operators.
Definition: iterator.h:257
bool operator<(const ConditionalIterator &other) const
Comparison operators.
Definition: iterator.h:255
bool operator>=(const ConditionalIterator &other) const
Comparison operators.
Definition: iterator.h:258
ConditionalIterator(I iterator, I end, F predicate)
Constructor.
Definition: iterator.h:215
bool operator<=(const ConditionalIterator &other) const
Comparison operators.
Definition: iterator.h:256
bool operator!=(const ConditionalIterator &other) const
Comparison operators.
Definition: iterator.h:254
I operator->()
Indirection operator, returns the underlying iterator. Undefined if iterator is at the end.
Definition: iterator.h:245
std::forward_iterator_tag iterator_category
Types.
Definition: iterator.h:207
bool operator==(const ConditionalIterator &other) const
Comparison operators.
Definition: iterator.h:253
Configurable output iterator using a provided functor to do the insertion.
Definition: iterator.h:24
OutputIterator(const F &func)
Constructor.
Definition: iterator.h:37
OutputIterator & operator*()
Dereference (no-op)
Definition: iterator.h:49
OutputIterator & operator=(T &&value)
Assignment operator performs the output.
Definition: iterator.h:53
std::output_iterator_tag iterator_category
Types.
Definition: iterator.h:28
OutputIterator(const OutputIterator &other)
Constructor.
Definition: iterator.h:39
OutputIterator(F &&func)
Constructor.
Definition: iterator.h:38
OutputIterator operator++(int)
Advance the iterator (no-op)
Definition: iterator.h:45
OutputIterator & operator=(const OutputIterator &other)
Copy assignment operator.
Definition: iterator.h:60
OutputIterator & operator++()
Advance the iterator (no-op)
Definition: iterator.h:44
Iterator wrapper which applies some transformation function to each element.
Definition: iterator.h:108
TransformIterator & operator++()
Advance to the next element. Undefined if iterator is at the end.
Definition: iterator.h:149
bool operator==(const TransformIterator &other) const
Comparison operators.
Definition: iterator.h:182
undecayed_type operator*()
Dereference operator, returns the transformed object reference by the iterator. Undefined if iterator...
Definition: iterator.h:164
bool operator>=(const TransformIterator &other) const
Comparison operators.
Definition: iterator.h:187
TransformIterator(I iterator, F function)
Constructor.
Definition: iterator.h:141
bool operator<=(const TransformIterator &other) const
Comparison operators.
Definition: iterator.h:185
std::decay_t< decltype(std::declval< F >()(std::declval< typename std::iterator_traits< I >::value_type >()))> value_type
Types.
Definition: iterator.h:114
TransformIterator operator++(int)
Advance to the next element. Undefined if iterator is at the end.
Definition: iterator.h:154
decltype(std::declval< F >()(std::declval< typename std::iterator_traits< I >::value_type >())) undecayed_type
The type returned by the transformation function, which may or may not be a reference.
Definition: iterator.h:121
bool operator>(const TransformIterator &other) const
Comparison operators.
Definition: iterator.h:186
std::forward_iterator_tag iterator_category
Types.
Definition: iterator.h:112
typename std::conditional< std::is_reference_v< undecayed_type >, std::remove_reference_t< undecayed_type > *, PointerWrapper >::type pointer
The type returned by this iterator's arrow operator, which may be a pointer or a pointer-like wrapper...
Definition: iterator.h:138
pointer operator->()
Indirection operator, returns a pointer to the transformed object, or a pointer-like wrapper object i...
Definition: iterator.h:173
TransformIterator(I end)
Implicit conversion from an end iterator.
Definition: iterator.h:144
bool operator<(const TransformIterator &other) const
Comparison operators.
Definition: iterator.h:184
typename std::iterator_traits< I >::reference reference
Types.
Definition: iterator.h:116
typename std::iterator_traits< I >::difference_type difference_type
Types.
Definition: iterator.h:115
bool operator!=(const TransformIterator &other) const
Comparison operators.
Definition: iterator.h:183
Iterator classes for the containers.
Definition: iterator.h:18
auto makeTransformIterator(I iterator, F function) -> TransformIterator< I, F >
Construct a TransformIterator of the appropriate type from deduced template function arguments.
Definition: iterator.h:343
auto makeInsertIterator(T &container)
Return an insert iterator appropriate to the container type (uses push_back or insert).
Definition: iterator.h:88
auto makeOutputIterator(F &&func)
Return an output iterator of type deduced from the argument.
Definition: iterator.h:79
auto makeConditionalIterator(I iterator, I end, F predicate) -> ConditionalIterator< I, F >
Construct a ConditionalIterator of the appropriate type from deduced template function arguments.
Definition: iterator.h:352
auto makeConcatIterator(QVector< I > iterators) -> ConcatIterator< I >
Construct a ConcatIterator of the appropriate type from deduced template function arguments.
Definition: iterator.h:361
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition: lockfree.h:338
Trait which is true if the expression a.push_back(v) is valid when a and v are instances of T and T::...
Definition: typetraits.h:71