1#ifndef LIBSBX_UTILITY_ZIP_HPP_
2#define LIBSBX_UTILITY_ZIP_HPP_
4namespace sbx::utility {
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
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 {
24 result = (... || (std::get<Index>(lhs) == std::get<Index>(rhs)));
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...>{});
33template<
typename... Iterators>
37 using value_type = std::tuple<select_access_type_for<Iterators>...>;
42 : _iterators {std::forward<Iterators>(iterators)...} { }
45 std::apply([](
auto&&... iterators){ ((iterators += 1), ...); }, _iterators);
56 return any_match(_iterators, other._iterators);
59 auto operator*() -> value_type {
60 return std::apply([](
auto&&... iterators){
61 return value_type(*iterators...);
67 std::tuple<Iterators...> _iterators;
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
78template<
typename... Containers>
85 template<
typename... Args>
86 zipper(Args&&... containers)
87 : _containers{std::forward<Args>(containers)...} { }
90 return std::apply([](
auto&& ... containers){
91 return iterator(std::begin(containers)...);
96 return std::apply([](
auto&& ... containers){
97 return iterator(std::end(containers)...);
103 std::tuple<Containers...> _containers;
109template<
typename... Containers>
110auto zip(Containers&&... containers) {
111 return detail::zipper<Containers...>{std::forward<Containers>(containers)...};