2#ifndef LIBSBX_UTILITY_ZIP_HPP_
3#define LIBSBX_UTILITY_ZIP_HPP_
5namespace sbx::utility {
14template<std::input_iterator Iterator>
15using select_access_type_for = std::conditional_t<
16 std::is_same_v<Iterator, std::vector<bool>::iterator> ||
17 std::is_same_v<Iterator, std::vector<bool>::const_iterator>,
18 typename Iterator::value_type,
19 typename Iterator::reference
22template<
typename... Args, std::size_t ... Index>
23auto any_match_impl(
const std::tuple<Args...>& lhs,
const std::tuple<Args...>& rhs, std::index_sequence<Index...>) ->
bool {
25 result = (... || (std::get<Index>(lhs) == std::get<Index>(rhs)));
29template<
typename... Args>
30auto any_match(
const std::tuple<Args...>& lhs,
const std::tuple<Args...>& rhs) ->
bool {
31 return any_match_impl(lhs, rhs, std::index_sequence_for<Args...>{});
34template<
typename... Iterators>
38 using value_type = std::tuple<select_access_type_for<Iterators>...>;
43 : _iterators {std::forward<Iterators>(iterators)...} { }
46 std::apply([](
auto&&... iterators){ ((iterators += 1), ...); }, _iterators);
57 return any_match(_iterators, other._iterators);
60 auto operator*() -> value_type {
61 return std::apply([](
auto&&... iterators){
62 return value_type(*iterators...);
68 std::tuple<Iterators...> _iterators;
72template<
typename Type>
73using select_iterator_for = std::conditional_t<
74 std::is_const_v<std::remove_reference_t<Type>>,
75 typename std::decay_t<Type>::const_iterator,
76 typename std::decay_t<Type>::iterator
79template<
typename... Containers>
86 template<
typename... Args>
87 zipper(Args&&... containers)
88 : _containers{std::forward<Args>(containers)...} { }
91 return std::apply([](
auto&& ... containers){
92 return iterator(std::begin(containers)...);
97 return std::apply([](
auto&& ... containers){
98 return iterator(std::end(containers)...);
104 std::tuple<Containers...> _containers;
110template<
typename... Containers>
111auto zip(Containers&&... containers) {
112 return detail::zipper<Containers...>{std::forward<Containers>(containers)...};