IgANet
IGAnets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
zip.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <array>
18#include <iterator>
19#include <stdexcept>
20#include <tuple>
21#include <utility>
22
23namespace iganet::utils {
24
25namespace detail {
26
27template <typename... T> class zip_helper {
28public:
29 class iterator {
30 public:
31 using iterator_category = std::forward_iterator_tag;
32 using value_type = std::tuple<decltype(*std::declval<T>().begin())...>;
33 using difference_type = std::tuple<decltype(*std::declval<T>().begin())...>;
34 using pointer = std::tuple<decltype(*std::declval<T>().begin())...> *;
35 using reference = std::tuple<decltype(*std::declval<T>().begin())...> &;
36
37 private:
38 std::tuple<decltype(std::declval<T>().begin())...> _iterators;
39
40 template <std::size_t... I> auto deref(std::index_sequence<I...>) const {
41 return iterator::value_type{*std::get<I>(_iterators)...};
42 }
43
44 template <std::size_t... I> void increment(std::index_sequence<I...>) {
45 auto l = {(++std::get<I>(_iterators), 0)...};
46 }
47
48 public:
52 explicit iterator(decltype(_iterators) iterators)
53 : _iterators{std::move(iterators)} {}
54
58 increment(std::index_sequence_for<T...>{});
59 return *this;
60 }
61
65 auto saved{*this};
66 increment(std::index_sequence_for<T...>{});
67 return saved;
68 }
69
73 bool operator!=(const iterator &other) const {
74 return _iterators != other._iterators;
75 }
76
79 auto operator*() const { return deref(std::index_sequence_for<T...>{}); }
80 };
81
84 zip_helper(T &&...seqs)
85 : _seqs(seqs...),
87 std::make_index_sequence<sizeof...(seqs)>{})},
88 _end{make_tuple_end(_seqs,
89 std::make_index_sequence<sizeof...(seqs)>{})} {
90 validate_lengths(std::make_index_sequence<sizeof...(seqs)>{});
91 }
92
95 iterator begin() const { return _begin; }
98 iterator end() const { return _end; }
99
100private:
101 template <std::size_t... Is>
102 void validate_lengths(std::index_sequence<Is...>) const {
103 if constexpr (sizeof...(Is) > 1) {
104 const std::array lengths{
105 std::distance(std::get<Is>(_seqs).begin(),
106 std::get<Is>(_seqs).end())...};
107 for (std::size_t i = 1; i < lengths.size(); ++i)
108 if (lengths[i] != lengths[0])
109 throw std::invalid_argument("zip requires equally sized ranges");
110 }
111 }
112
113 template <typename Tuple, std::size_t... Is>
114 auto constexpr make_tuple_begin(Tuple &&t, std::index_sequence<Is...>) {
115 return std::make_tuple(std::get<Is>(t).begin()...);
116 }
117
118 template <typename Tuple, std::size_t... Is>
119 auto constexpr make_tuple_end(Tuple &&t, std::index_sequence<Is...>) {
120 return std::make_tuple(std::get<Is>(t).end()...);
121 }
122
123private:
124 std::tuple<T...> _seqs;
127};
128
129} // namespace detail
130
134// Sequences must be the same length.
135template <typename... T> auto zip(T &&...seqs) {
136 return iganet::utils::detail::zip_helper<T...>(std::forward<T>(seqs)...);
137}
138
139} // namespace iganet::utils
std::tuple< decltype(*std::declval< T >().begin())... > & reference
Definition zip.hpp:35
std::forward_iterator_tag iterator_category
Definition zip.hpp:31
void increment(std::index_sequence< I... >)
Definition zip.hpp:44
auto deref(std::index_sequence< I... >) const
Definition zip.hpp:40
std::tuple< decltype(*std::declval< T >().begin())... > value_type
Definition zip.hpp:32
auto operator*() const
Provides the operator* operation.
Definition zip.hpp:79
std::tuple< decltype(std::declval< T >().begin())... > _iterators
Definition zip.hpp:38
bool operator!=(const iterator &other) const
Provides the operator!= operation.
Definition zip.hpp:73
iterator(decltype(_iterators) iterators)
Provides the iterator operation.
Definition zip.hpp:52
iterator & operator++()
Provides the operator++ operation.
Definition zip.hpp:57
std::tuple< decltype(*std::declval< T >().begin())... > * pointer
Definition zip.hpp:34
std::tuple< decltype(*std::declval< T >().begin())... > difference_type
Definition zip.hpp:33
iterator operator++(int)
Provides the operator++ operation.
Definition zip.hpp:64
auto constexpr make_tuple_begin(Tuple &&t, std::index_sequence< Is... >)
Definition zip.hpp:114
zip_helper(T &&...seqs)
Provides the zip_helper operation.
Definition zip.hpp:84
iterator end() const
Provides the end operation.
Definition zip.hpp:98
iterator begin() const
Provides the begin operation.
Definition zip.hpp:95
iterator _end
Definition zip.hpp:126
auto constexpr make_tuple_end(Tuple &&t, std::index_sequence< Is... >)
Definition zip.hpp:119
void validate_lengths(std::index_sequence< Is... >) const
Definition zip.hpp:102
iterator _begin
Definition zip.hpp:125
std::tuple< T... > _seqs
Definition zip.hpp:124
Definition blocktensor.hpp:24
auto zip(T &&...seqs)
Provides the zip operation.
Definition zip.hpp:135
STL namespace.