1 #ifndef MSD_ZIP_ZIP_HPP
2 #define MSD_ZIP_ZIP_HPP
20 template <
typename... Iterators>
36 using value_type = std::tuple<typename std::iterator_traits<Iterators>::reference...>;
41 using pointer = std::tuple<typename std::iterator_traits<Iterators>::pointer...>;
46 using reference = std::tuple<typename std::iterator_traits<Iterators>::reference...>;
53 explicit zip_iterator(Iterators... iterators) : iterators_{iterators...} {}
85 advance(std::index_sequence_for<Iterators...>{}, 1);
97 auto iterator = *
this;
98 iterator.advance(std::index_sequence_for<Iterators...>{}, offset);
110 auto iterator = *
this;
111 const auto distance = std::distance(iterator, other);
112 iterator.advance(std::index_sequence_for<Iterators...>{}, distance);
123 advance(std::index_sequence_for<Iterators...>{}, -1);
135 auto iterator = *
this;
136 iterator.advance(std::index_sequence_for<Iterators...>{}, -offset);
148 auto iterator = *
this;
149 const auto distance = std::distance(other, iterator);
150 iterator.advance(std::index_sequence_for<Iterators...>{}, -distance);
162 template <std::size_t... I>
163 value_type dereference(std::index_sequence<I...>)
const
165 return std::tie(*std::get<I>(iterators_)...);
176 template <std::size_t... I>
177 bool equal(std::index_sequence<I...>,
const zip_iterator& other)
const
179 return ((std::get<I>(iterators_) == std::get<I>(other.iterators_)) || ...);
189 template <std::size_t... I>
190 void advance(std::index_sequence<I...>,
const int offset)
192 ((std::advance(std::get<I>(iterators_), offset)), ...);
198 std::tuple<Iterators...> iterators_;
211 template <
typename... Containers>
214 static_assert(
sizeof...(Containers) > 1,
"zip requires at least 2 containers");
224 typename Containers::iterator>...>;
244 explicit zip(Containers&... containers) : containers_{containers...} {}
251 iterator begin()
const {
return begin_impl<iterator>(std::index_sequence_for<Containers...>{}); }
258 iterator end()
const {
return end_impl<iterator>(std::index_sequence_for<Containers...>{}); }
272 const_iterator cend()
const {
return end_impl<const_iterator>(std::index_sequence_for<Containers...>{}); }
279 [[nodiscard]] std::size_t
size()
const {
return size_impl(std::index_sequence_for<Containers...>{}); }
294 explicit operator bool()
const {
return !
empty(); }
353 assert(offset <
size());
354 return *std::next(
begin(), offset);
366 template <
typename Iterator, std::size_t... I>
367 Iterator begin_impl(std::index_sequence<I...>)
const
369 return Iterator{std::get<I>(containers_).begin()...};
380 template <
typename Iterator, std::size_t... I>
381 Iterator end_impl(std::index_sequence<I...>)
const
383 return std::next(Iterator{std::get<I>(containers_).begin()...},
size());
393 template <std::size_t... I>
394 std::size_t size_impl(std::index_sequence<I...>)
const
396 return std::min({std::distance(std::get<I>(containers_).
begin(), std::get<I>(containers_).
end())...});
402 std::tuple<Containers&...> containers_;
Bidirectional iterator over multiple iterators simultaneously.
Definition: zip.hpp:21
bool operator==(const zip_iterator &other) const
Checks if two zip_iterator instances are equal.
Definition: zip.hpp:68
zip_iterator & operator++()
Advances the zip_iterator by one position.
Definition: zip.hpp:83
zip_iterator & operator--()
Moves the zip_iterator back by one position.
Definition: zip.hpp:121
std::bidirectional_iterator_tag iterator_category
Supports bidirectional traversal.
Definition: zip.hpp:26
bool operator!=(const zip_iterator &other) const
Checks if two zip_iterator instances are not equal.
Definition: zip.hpp:76
std::tuple< typename std::iterator_traits< Iterators >::reference... > value_type
A tuple of references from each of the zipped iterators.
Definition: zip.hpp:36
zip_iterator operator+(const std::size_t offset) const
Returns a new zip_iterator advanced by a specified offset.
Definition: zip.hpp:95
zip_iterator operator-(const int offset) const
Returns a new zip_iterator moved back by a specified offset.
Definition: zip.hpp:133
std::ptrdiff_t difference_type
The difference between two iterators.
Definition: zip.hpp:31
value_type operator*() const
Dereferences the zip_iterator to obtain a tuple of references from each iterator.
Definition: zip.hpp:60
zip_iterator(Iterators... iterators)
Constructs a zip_iterator from the provided iterators.
Definition: zip.hpp:53
zip_iterator operator+(const zip_iterator &other) const
Returns a new zip_iterator advanced by the distance between two iterators.
Definition: zip.hpp:108
zip_iterator operator-(const zip_iterator &other) const
Returns the distance between two zip_iterator instances.
Definition: zip.hpp:146
std::tuple< typename std::iterator_traits< Iterators >::pointer... > pointer
A tuple of pointers from each of the zipped iterators.
Definition: zip.hpp:41
std::tuple< typename std::iterator_traits< Iterators >::reference... > reference
A tuple of references from each of the zipped iterators.
Definition: zip.hpp:46
A view over multiple containers simultaneously. It allows iterating through multiple containers at on...
Definition: zip.hpp:212
const_iterator cbegin() const
Returns a const iterator pointing to the beginning of the zipped containers.
Definition: zip.hpp:265
value_type back() const
Returns the last element in the zipped sequence (const overload).
Definition: zip.hpp:338
value_type front()
Returns the first element in the zipped sequence.
Definition: zip.hpp:302
const_iterator cend() const
Returns a const iterator pointing to the end of the zipped containers.
Definition: zip.hpp:272
value_type operator[](const std::size_t offset) const
Returns the element at the specified offset in the zipped sequence.
Definition: zip.hpp:351
iterator begin() const
Returns an iterator pointing to the beginning of the zipped containers.
Definition: zip.hpp:251
value_type front() const
Returns the first element in the zipped sequence (const overload).
Definition: zip.hpp:314
value_type back()
Returns the last element in the zipped sequence.
Definition: zip.hpp:326
zip(Containers &... containers)
Constructs a zip object from the provided containers.
Definition: zip.hpp:244
bool empty() const
Checks if the zipped sequence is empty.
Definition: zip.hpp:286
std::size_t size() const
Returns the size of the zipped sequence, which is the size of the smallest container.
Definition: zip.hpp:279
typename iterator::value_type value_type
The value_type is the type of the element returned by the iterator, which is a tuple of elements from...
Definition: zip.hpp:236
iterator end() const
Returns an iterator pointing to the end of the zipped containers.
Definition: zip.hpp:258