9 #ifndef EAGINE_ZIP_ITERATOR_HPP
10 #define EAGINE_ZIP_ITERATOR_HPP
14 #include <type_traits>
19 template <
typename... Iter>
22 using _idx_seq = std::make_index_sequence<
sizeof...(Iter)>;
23 using _iters_t = std::tuple<Iter...>;
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)...);
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)...);
36 template <
typename IT,
typename Func, std::size_t... I>
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)));
42 template <
typename IT,
typename Func, std::size_t... I>
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)));
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)));
54 using difference_type = std::ptrdiff_t;
56 constexpr zip_iterator(Iter... iters)
59 friend auto operator==(
const zip_iterator& a,
const zip_iterator& b) {
63 [](
auto ia,
auto ib) { return ia == ib; },
67 friend auto operator!=(
const zip_iterator& a,
const zip_iterator& b) {
71 [](
auto ia,
auto ib) { return ia != ib; },
75 auto operator++() ->
auto& {
77 _iters, [](
auto& i) { ++i; }, _idx_seq{});
81 auto operator*()
const {
82 return _tie_deref(_iters, _idx_seq{});
86 return _tie_deref(_iters, _idx_seq{});
90 template <
typename... Iter>
91 static inline auto zip_iters(Iter... i) {
92 return zip_iterator<Iter...>{i...};
95 template <
typename... Range>
96 class zipped_range_refs {
98 using _idx_seq = std::make_index_sequence<
sizeof...(Range)>;
99 using _rrefs_t = std::tuple<Range&...>;
102 template <
typename RR, std::size_t... I>
103 static auto _zip_bgn(RR& r, std::index_sequence<I...>) {
105 return zip_iters(std::begin(std::get<I>(r))...);
108 template <
typename RR, std::size_t... I>
109 static auto _zip_end(RR& r, std::index_sequence<I...>) {
111 return zip_iters(std::end(std::get<I>(r))...);
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)...);
120 zipped_range_refs(Range&... ranges) noexcept
121 : _rrefs(ranges...) {}
124 return _zip_bgn(_rrefs, _idx_seq{});
127 return _zip_bgn(_rrefs, _idx_seq{});
131 return _zip_end(_rrefs, _idx_seq{});
134 return _zip_end(_rrefs, _idx_seq{});
137 template <
typename Func>
138 void for_each(Func func) {
139 for(
auto tup : *
this) {
140 _deref_call(tup, func, _idx_seq{});
145 template <
typename... Range>
146 static inline auto zip_ranges(Range&... ranges) noexcept {
147 return zipped_range_refs<Range...>{ranges...};
152 #endif // EAGINE_ZIP_ITERATOR_HPP