sandbox
Loading...
Searching...
No Matches
zip.hpp
1#ifndef LIBSBX_UTILITY_ZIP_HPP_
2#define LIBSBX_UTILITY_ZIP_HPP_
3
4namespace sbx::utility {
5
6#include <type_traits>
7#include <concepts>
8#include <vector>
9#include <utility>
10
11namespace detail {
12
13template<std::input_iterator Iterator>
14using select_access_type_for = std::conditional_t<
15 std::is_same_v<Iterator, std::vector<bool>::iterator> ||
16 std::is_same_v<Iterator, std::vector<bool>::const_iterator>,
17 typename Iterator::value_type,
18 typename Iterator::reference
19>;
20
21template<typename... Args, std::size_t ... Index>
22auto any_match_impl(const std::tuple<Args...>& lhs, const std::tuple<Args...>& rhs, std::index_sequence<Index...>) -> bool {
23 auto result = false;
24 result = (... || (std::get<Index>(lhs) == std::get<Index>(rhs)));
25 return result;
26}
27
28template<typename... Args>
29auto any_match(const std::tuple<Args...>& lhs, const std::tuple<Args...>& rhs) -> bool {
30 return any_match_impl(lhs, rhs, std::index_sequence_for<Args...>{});
31}
32
33template<typename... Iterators>
35public:
36
37 using value_type = std::tuple<select_access_type_for<Iterators>...>;
38
39 zip_iterator() = delete;
40
41 zip_iterator(Iterators&&... iterators)
42 : _iterators {std::forward<Iterators>(iterators)...} { }
43
44 auto operator++() -> zip_iterator& {
45 std::apply([](auto&&... iterators){ ((iterators += 1), ...); }, _iterators);
46 return *this;
47 }
48
49 auto operator++(int) -> zip_iterator {
50 auto copy = *this;
51 ++(*this);
52 return copy;
53 }
54
55 auto operator==(const zip_iterator& other) {
56 return any_match(_iterators, other._iterators);
57 }
58
59 auto operator*() -> value_type {
60 return std::apply([](auto&&... iterators){
61 return value_type(*iterators...);
62 }, _iterators);
63 }
64
65private:
66
67 std::tuple<Iterators...> _iterators;
68
69};
70
71template<typename Type>
72using select_iterator_for = std::conditional_t<
73 std::is_const_v<std::remove_reference_t<Type>>,
74 typename std::decay_t<Type>::const_iterator,
75 typename std::decay_t<Type>::iterator
76>;
77
78template<typename... Containers>
79class zipper {
80
81public:
82
84
85 template<typename... Args>
86 zipper(Args&&... containers)
87 : _containers{std::forward<Args>(containers)...} { }
88
89 auto begin() -> iterator {
90 return std::apply([](auto&& ... containers){
91 return iterator(std::begin(containers)...);
92 }, _containers);
93 }
94
95 auto end() -> iterator {
96 return std::apply([](auto&& ... containers){
97 return iterator(std::end(containers)...);
98 }, _containers);
99 }
100
101private:
102
103 std::tuple<Containers...> _containers;
104
105}; // class zipper
106
107} // namespace detail
108
109template<typename... Containers>
110auto zip(Containers&&... containers) {
111 return detail::zipper<Containers...>{std::forward<Containers>(containers)...};
112}
113
114} // namespace sbx::utility
115
116#endif // LIBSBX_UTILITY_ZIP_HPP_
Definition: zip.hpp:79