Utopia  2
Framework for studying models of complex & adaptive systems.
zip.hh
Go to the documentation of this file.
1 #ifndef UTOPIA_CORE_ZIP_HH
2 #define UTOPIA_CORE_ZIP_HH
3 
4 #include <iterator>
5 #include <tuple>
6 #include <type_traits>
7 #include <iterator>
8 #include <iostream>
9 
10 #include <boost/hana/ext/std/tuple.hpp>
11 #include <boost/hana/transform.hpp>
12 #include <boost/hana/for_each.hpp>
13 
14 #include "type_traits.hh"
15 
16 namespace Utopia
17 {
18 
20 
22 namespace Itertools
23 {
24 
26 
40 template <typename... Iters>
42 {
43 private:
44  using Tuple = std::tuple<Iters...>;
45 
46  using RefTuple = std::tuple<decltype(*std::declval<Iters>())...>;
47 
48  using PtrTuple = std::tuple<typename std::iterator_traits<Iters>::pointer...>;
49 
51 
52  using This = ZipIterator<Iters...>;
53 
54 public:
55  using value_type = std::tuple<typename std::iterator_traits<Iters>::value_type...>;
56  using difference_type = int;
57  using pointer = PtrTuple;
60  std::common_type_t<typename std::iterator_traits<Iters>::iterator_category...>;
61 
63 
66  {
67  boost::hana::for_each(_iterators, [](auto&& iter) { ++iter; });
68  return *this;
69  }
70 
72 
74  template<typename category = iterator_category,
75  typename std::enable_if_t<
76  std::is_base_of_v<std::bidirectional_iterator_tag,
77  category>, int> = 0>
79  {
80  boost::hana::for_each(_iterators, [](auto&& iter) { --iter; });
81  return *this;
82  }
83 
85 
88  {
89  This copy(*this);
90  boost::hana::for_each(_iterators, [](auto&& iter) { iter++; });
91  return copy;
92  }
93 
95 
97  template<typename category = iterator_category,
98  typename std::enable_if_t<
99  std::is_base_of_v<std::bidirectional_iterator_tag,
100  category>, int> = 0>
102  {
103  This copy(*this);
104  boost::hana::for_each(_iterators, [](auto&& iter) { iter--; });
105  return copy;
106  }
107 
109 
112  template<typename category = iterator_category,
113  typename std::enable_if_t<
114  std::is_base_of_v<std::random_access_iterator_tag,
115  category>, int> = 0>
117  {
118  This copy(*this);
119  return copy += n;
120  }
121 
123 
126  template<typename category = iterator_category,
127  typename std::enable_if_t<
128  std::is_base_of_v<std::random_access_iterator_tag,
129  category>, int> = 0>
131  {
132  This copy(*this);
133  return copy -= n;
134  }
135 
137 
140  template<typename category = iterator_category,
141  typename std::enable_if_t<
142  std::is_base_of_v<std::random_access_iterator_tag,
143  category>, int> = 0>
145  {
146  return std::get<0>(_iterators) - std::get<0>(other._iterators);
147  }
148 
150 
153  template<typename category = iterator_category,
154  typename std::enable_if_t<
155  std::is_base_of_v<std::random_access_iterator_tag,
156  category>, int> = 0>
158  {
159  boost::hana::for_each(_iterators, [&n](auto&& iter) { iter += n; });
160  return *this;
161  }
162 
164 
167  template<typename category = iterator_category,
168  typename std::enable_if_t<
169  std::is_base_of_v<std::random_access_iterator_tag,
170  category>, int> = 0>
172  {
173  boost::hana::for_each(_iterators, [&n](auto&& iter) { iter -= n; });
174  return *this;
175  }
176 
178 
180  const reference operator*() const
181  {
182  return boost::hana::transform(
183  _iterators,
184  [](auto&& iter) { return std::ref(*iter); });
185  }
186 
188 
191  {
192  return boost::hana::transform(
193  _iterators,
194  [](auto&& iter) { return std::ref(*iter); });
195  }
196 
198 
200  const pointer operator->() const
201  {
202  return boost::hana::transform(
203  _iterators,
204  [](auto&& iter) { return &(*iter); });
205  }
206 
208 
211  {
212  return boost::hana::transform(
213  _iterators,
214  [](auto&& iter) { return &(*iter); });
215  }
216 
218  ZipIterator() = default;
219 
221 
223  ZipIterator(const ZipIterator& other) = default;
224 
226 
229  ZipIterator(ZipIterator&& other) = default;
230 
232 
236  ZipIterator& operator=(ZipIterator&& other) = default;
237 
239 
242  ZipIterator& operator=(const ZipIterator& other)= default;
243 
245 
247  ZipIterator(Iters... iters)
248  : _iterators(std::make_tuple(iters...))
249  {
250  }
251 
253 
255  template <typename... Iterators>
256  ZipIterator(std::tuple<Iterators...> iters) : _iterators(iters)
257  {
258  }
259 
261 
265  template<typename... It>
266  bool operator==(const ZipIterator<It...>& other) const
267  {
268  return _iterators == other._iterators;
269  }
270 
272 
276  template<typename... It>
277  bool operator!=(const ZipIterator<It...>& other) const
278  {
279  return _iterators != other._iterators;
280  }
281 
283 
287  template<typename category = iterator_category,
288  typename std::enable_if_t<
289  std::is_base_of_v<std::random_access_iterator_tag,
290  category>, int> = 0>
291  bool operator<(const ZipIterator& other) const
292  {
293  return _iterators < other._iterators;
294  }
295 
297 
301  template<typename category = iterator_category,
302  typename std::enable_if_t<
303  std::is_base_of_v<std::random_access_iterator_tag,
304  category>, int> = 0>
305  bool operator<=(const ZipIterator& other) const
306  {
307  return _iterators <= other._iterators;
308  }
309 
311 
315  template<typename category = iterator_category,
316  typename std::enable_if_t<
317  std::is_base_of_v<std::random_access_iterator_tag,
318  category>, int> = 0>
319  bool operator>(const ZipIterator& other) const
320  {
321  return _iterators > other._iterators;
322  }
323 
325 
329  template<typename category = iterator_category,
330  typename std::enable_if_t<
331  std::is_base_of_v<std::random_access_iterator_tag,
332  category>, int> = 0>
333  bool operator>=(const ZipIterator& other) const
334  {
335  return _iterators >= other._iterators;
336  }
337 
345 
352  template<typename category = iterator_category,
353  typename std::enable_if_t<
354  std::is_base_of_v<std::random_access_iterator_tag,
355  category>, int> = 0>
357  {
358  return *(*this + n);
359  }
360 
362  ~ZipIterator() = default;
363 
365 
367  friend std::ostream& operator<< (std::ostream& ostr,
368  const ZipIterator& right
369  )
370  {
371  // using Utopia::Utils::operator<<;
372  ostr << "->" << *right;
373  return ostr;
374  }
375 };
376 
378 template <typename... Iterators>
379 ZipIterator(std::tuple<Iterators...> iters)->ZipIterator<Iterators...>;
380 
381 // iterator adaptors
382 
384 
395 template <typename Adaptor, typename... Containers>
396 auto adapt_zip(Adaptor&& adaptor, Containers&... containers)
397 {
398  return ZipIterator(adaptor(containers)...);
399 }
400 
402 
408 template <typename... Containers>
409 class zip
410 {
411 protected:
412  using Tuple = std::tuple<std::reference_wrapper<Containers>...>;
414 
415 public:
422  auto begin()
423  {
425  _containers, [](auto& cont) { return cont.get().begin(); }));
426  }
427 
434  auto end()
435  {
437  _containers, [](auto& cont) { return cont.get().end(); }));
438  }
439 
446  auto cbegin()
447  {
449  _containers, [](auto& cont) { return cont.get().cbegin(); }));
450  }
451 
458  auto cend()
459  {
461  _containers, [](auto& cont) { return cont.get().cend(); }));
462  }
463 
470  auto rbegin()
471  {
473  _containers, [](auto& cont) { return cont.get().rbegin(); }));
474  }
475 
482  auto rend()
483  {
485  _containers, [](auto& cont) { return cont.get().rend(); }));
486  }
487 
493  zip(const zip& other) = delete;
494 
501  zip& operator=(const zip& other) = delete;
502 
509  zip& operator=(zip&& other) = default;
510 
516  zip(zip&& other) = default;
517 
519  ~zip() = default;
520 
522 
524  zip(Containers&... conts) : _containers(conts...)
525  {
526  }
527 };
528 
536 template <typename... Containers>
538 {
539  return zipper.begin();
540 }
541 
549 template <typename... Containers>
550 auto end(zip<Containers...>& zipper)
551 {
552  return zipper.end();
553 }
554 
562 template <typename... Containers>
564 {
565  return zipper.cbegin();
566 }
567 
575 template <typename... Containers>
577 {
578  return zipper.cend();
579 }
580 
588 template <typename... Containers>
590 {
591  return zipper.rbegin();
592 }
593 
601 template <typename... Containers>
603 {
604  return zipper.rend();
605 }
606 
611 } // namespace Itertools
612 } // namespace Utopia
613 
614 #endif // UTOPIA_CORE_ZIP_HH
Iterator over an arbitrary number of collections.
Definition: zip.hh:42
reference operator*()
Dereference this iterator at its current position.
Definition: zip.hh:190
bool operator<=(const ZipIterator &other) const
Less-than or equal compare this object with another zip iterator.
Definition: zip.hh:305
const pointer operator->() const
Indirect this pointer at its current position.
Definition: zip.hh:200
std::tuple< typename std::iterator_traits< Iters >::value_type... > value_type
Definition: zip.hh:55
ZipIterator & operator-=(const difference_type n)
Decrement in-place by a number of steps.
Definition: zip.hh:171
ZipIterator operator--(int)
Decrement by postfix.
Definition: zip.hh:101
ZipIterator & operator=(ZipIterator &&other)=default
Move-assign a zip iterator.
difference_type operator-(const ZipIterator &other) const
Compute the difference between two iterators.
Definition: zip.hh:144
std::tuple< typename std::iterator_traits< Iters >::pointer... > PtrTuple
Definition: zip.hh:48
ZipIterator & operator++()
Increment by prefix.
Definition: zip.hh:65
ZipIterator(Iters... iters)
Construct from a pack of iterators.
Definition: zip.hh:247
reference operator[](const difference_type n) const
offset dereference operator for purely random accesss iterators held by ZipIterator
Definition: zip.hh:356
bool operator==(const ZipIterator< It... > &other) const
Compare this object with another zip iterator.
Definition: zip.hh:266
bool operator<(const ZipIterator &other) const
Less-than compare this object with another zip iterator.
Definition: zip.hh:291
friend std::ostream & operator<<(std::ostream &ostr, const ZipIterator &right)
Write the contents of this iterator into an outstream.
Definition: zip.hh:367
ZipIterator & operator--()
Decrement by prefix.
Definition: zip.hh:78
ZipIterator & operator+=(const difference_type n)
Increment in-place by a number of steps.
Definition: zip.hh:157
ZipIterator operator++(int)
Increment by postfix.
Definition: zip.hh:87
ZipIterator()=default
Default-construct a zip iterator. Dereferencing it is undefined.
bool operator!=(const ZipIterator< It... > &other) const
Compare this object with another zip iterator.
Definition: zip.hh:277
ZipIterator(const ZipIterator &other)=default
Copy-construct a zip iterator.
std::tuple< decltype(*std::declval< Iters >())... > RefTuple
Definition: zip.hh:46
~ZipIterator()=default
Destroy this object.
ZipIterator operator-(const difference_type n) const
Decrement by a number of steps.
Definition: zip.hh:130
const reference operator*() const
Dereference this iterator at its current position.
Definition: zip.hh:180
std::common_type_t< typename std::iterator_traits< Iters >::iterator_category... > iterator_category
Definition: zip.hh:60
PtrTuple pointer
Definition: zip.hh:57
ZipIterator operator+(const difference_type n) const
Increment by a number of steps.
Definition: zip.hh:116
ZipIterator(ZipIterator &&other)=default
Move-construct a zip iterator.
int difference_type
Definition: zip.hh:56
ZipIterator & operator=(const ZipIterator &other)=default
Copy-assign a zip iterator.
std::tuple< Iters... > Tuple
Definition: zip.hh:44
pointer operator->()
Indirect this pointer at its current position.
Definition: zip.hh:210
Tuple _iterators
Definition: zip.hh:50
bool operator>=(const ZipIterator &other) const
Greater-than or equal compare this object with another zip iterator.
Definition: zip.hh:333
RefTuple reference
Definition: zip.hh:58
ZipIterator(std::tuple< Iterators... > iters)
Construct from a tuple of iterators.
Definition: zip.hh:256
bool operator>(const ZipIterator &other) const
Greater-than compare this object with another zip iterator.
Definition: zip.hh:319
A range defined by instances of ZipIterator.
Definition: zip.hh:410
zip(zip &&other)=default
Construct a new zip object.
zip & operator=(const zip &other)=delete
deleted copy assignment
zip(Containers &... conts)
Instantiate a new zip range.
Definition: zip.hh:524
auto begin()
make Zipiterator containing the begin iterators of the containers 'zip' refers to
Definition: zip.hh:422
auto rbegin()
make Zipiterator containing the reverse begin iterators of the containers 'zip' refers to
Definition: zip.hh:470
auto rend()
make Zipiterator containing the reverse end iterators of the containers 'zip' refers to
Definition: zip.hh:482
auto cend()
make Zipiterator containing the const end iterators of the containers 'zip' refers to
Definition: zip.hh:458
auto cbegin()
make Zipiterator containing the const begin iterators of the containers 'zip' refers to
Definition: zip.hh:446
auto end()
make Zipiterator containing the end iterators of the containers 'zip' refers to
Definition: zip.hh:434
zip(const zip &other)=delete
Construct a new zip object.
zip & operator=(zip &&other)=default
assign zip object
~zip()=default
Destroy the range.
std::tuple< std::reference_wrapper< Containers >... > Tuple
Definition: zip.hh:412
Tuple _containers
Definition: zip.hh:413
OutputIt copy(const Utopia::ExecPolicy policy, InputIt first, InputIt last, OutputIt d_first)
Copy the input range to a new range.
Definition: parallel.hh:324
OutputIt transform(const Utopia::ExecPolicy policy, InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op)
Apply a unary operator to a range and store the result in a new range.
Definition: parallel.hh:368
void for_each(const Utopia::ExecPolicy policy, InputIt first, InputIt last, UnaryFunction f)
Apply a function to a range.
Definition: parallel.hh:346
auto adapt_zip(Adaptor &&adaptor, Containers &... containers)
Return a zip iterator built from an adapter applied to containers.
Definition: zip.hh:396
auto end(zip< Containers... > &zipper)
end function like std::end
Definition: zip.hh:550
ZipIterator(std::tuple< Iterators... > iters) -> ZipIterator< Iterators... >
Deduce the iterator types from the types inside the tuple.
auto begin(zip< Containers... > &zipper)
Begin function like std::begin.
Definition: zip.hh:537
auto cend(zip< Containers... > &zipper)
end function like std::end
Definition: zip.hh:576
auto rbegin(zip< Containers... > &zipper)
Begin function like std::begin.
Definition: zip.hh:589
auto rend(zip< Containers... > &zipper)
end function like std::end
Definition: zip.hh:602
auto cbegin(zip< Containers... > &zipper)
Begin function like std::begin.
Definition: zip.hh:563
Definition: agent.hh:11
Definition: parallel.hh:235