OGLplus  (0.59.0) a C++ wrapper for rendering APIs

zip_iterator.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_ZIP_ITERATOR_HPP
10 #define EAGINE_ZIP_ITERATOR_HPP
11 
12 #include <iterator>
13 #include <tuple>
14 #include <type_traits>
15 #include <utility>
16 
17 namespace eagine {
18 
19 template <typename... Iter>
20 class zip_iterator {
21 private:
22  using _idx_seq = std::make_index_sequence<sizeof...(Iter)>;
23  using _iters_t = std::tuple<Iter...>;
24  _iters_t _iters;
25 
26  template <std::size_t... I>
27  static auto _tie_deref(const _iters_t& a, std::index_sequence<I...>) {
28  return std::tie(*std::get<I>(a)...);
29  }
30 
31  template <typename IT, std::size_t... I>
32  static auto _tie_deref(IT& a, std::index_sequence<I...>) {
33  return std::tie(*std::get<I>(a)...);
34  }
35 
36  template <typename IT, typename Func, std::size_t... I>
37  static constexpr auto
38  _fold_or_2(IT& a, IT& b, Func func, std::index_sequence<I...>) {
39  return (... || func(std::get<I>(a), std::get<I>(b)));
40  }
41 
42  template <typename IT, typename Func, std::size_t... I>
43  static constexpr auto
44  _fold_and_2(IT& a, IT& b, Func func, std::index_sequence<I...>) {
45  return (... && func(std::get<I>(a), std::get<I>(b)));
46  }
47 
48  template <typename IT, typename Func, std::size_t... I>
49  static void _for_each_1(IT& a, Func func, std::index_sequence<I...>) {
50  return (..., func(std::get<I>(a)));
51  }
52 
53 public:
54  using difference_type = std::ptrdiff_t;
55 
56  constexpr zip_iterator(Iter... iters)
57  : _iters(iters...) {}
58 
59  friend auto operator==(const zip_iterator& a, const zip_iterator& b) {
60  return _fold_and_2(
61  a._iters,
62  b._iters,
63  [](auto ia, auto ib) { return ia == ib; },
64  _idx_seq{});
65  }
66 
67  friend auto operator!=(const zip_iterator& a, const zip_iterator& b) {
68  return _fold_or_2(
69  a._iters,
70  b._iters,
71  [](auto ia, auto ib) { return ia != ib; },
72  _idx_seq{});
73  }
74 
75  auto operator++() -> auto& {
76  _for_each_1(
77  _iters, [](auto& i) { ++i; }, _idx_seq{});
78  return *this;
79  }
80 
81  auto operator*() const {
82  return _tie_deref(_iters, _idx_seq{});
83  }
84 
85  auto operator*() {
86  return _tie_deref(_iters, _idx_seq{});
87  }
88 };
89 
90 template <typename... Iter>
91 static inline auto zip_iters(Iter... i) {
92  return zip_iterator<Iter...>{i...};
93 }
94 
95 template <typename... Range>
96 class zipped_range_refs {
97 private:
98  using _idx_seq = std::make_index_sequence<sizeof...(Range)>;
99  using _rrefs_t = std::tuple<Range&...>;
100  _rrefs_t _rrefs;
101 
102  template <typename RR, std::size_t... I>
103  static auto _zip_bgn(RR& r, std::index_sequence<I...>) {
104  using std::begin;
105  return zip_iters(std::begin(std::get<I>(r))...);
106  }
107 
108  template <typename RR, std::size_t... I>
109  static auto _zip_end(RR& r, std::index_sequence<I...>) {
110  using std::end;
111  return zip_iters(std::end(std::get<I>(r))...);
112  }
113 
114  template <typename Tup, typename Func, std::size_t... I>
115  static void _deref_call(Tup& tup, Func& func, std::index_sequence<I...>) {
116  func(std::get<I>(tup)...);
117  }
118 
119 public:
120  zipped_range_refs(Range&... ranges) noexcept
121  : _rrefs(ranges...) {}
122 
123  auto begin() {
124  return _zip_bgn(_rrefs, _idx_seq{});
125  }
126  auto begin() const {
127  return _zip_bgn(_rrefs, _idx_seq{});
128  }
129 
130  auto end() {
131  return _zip_end(_rrefs, _idx_seq{});
132  }
133  auto end() const {
134  return _zip_end(_rrefs, _idx_seq{});
135  }
136 
137  template <typename Func>
138  void for_each(Func func) {
139  for(auto tup : *this) {
140  _deref_call(tup, func, _idx_seq{});
141  }
142  }
143 };
144 
145 template <typename... Range>
146 static inline auto zip_ranges(Range&... ranges) noexcept {
147  return zipped_range_refs<Range...>{ranges...};
148 }
149 
150 } // namespace eagine
151 
152 #endif // EAGINE_ZIP_ITERATOR_HPP
Common code is placed in this namespace.
Definition: eagine.hpp:21
static constexpr auto operator!=(const valid_if< T, P1 > &v1, const valid_if< T, P2 > &v2) noexcept -> tribool
Non-equality comparison of two conditionally valid values.
Definition: decl.hpp:169
auto operator==(message_id l, static_message_id< ClassId, MethodId > r) noexcept
Equality comparison between message_id and static_message_id.
Definition: message_id.hpp:131

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).