zip_iterator.h 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #pragma once
  2. #include <iterator>
  3. #include <tuple>
  4. #include <iterator/facade.h>
  5. #include <iterator/forwards.h>
  6. namespace iterator::detail {
  7. template <typename Tuple, typename IS> class zip_iterator_impl;
  8. template <typename... Ts, size_t... Is>
  9. class zip_iterator_impl<std::tuple<Ts...>, std::index_sequence<Is...>> {
  10. public:
  11. using difference_type =
  12. std::common_type_t<typename std::iterator_traits<Ts>::difference_type...>;
  13. public:
  14. zip_iterator_impl() = default;
  15. zip_iterator_impl(Ts... iters) : _data(iters...) {}
  16. auto dereference() const {
  17. return std::forward_as_tuple(*std::get<Is>(_data)...);
  18. }
  19. void increment() {
  20. [[maybe_unused]] auto l = {((++std::get<Is>(_data)), 0)...};
  21. }
  22. void decrement() {
  23. [[maybe_unused]] auto l = {((++std::get<Is>(_data)), 0)...};
  24. }
  25. void advance(difference_type d) {
  26. [[maybe_unused]] auto l = {((std::get<Is>(_data) += d), 0)...};
  27. }
  28. bool equal_to(zip_iterator_impl const & other) const {
  29. return _data == other._data;
  30. }
  31. auto distance_to(zip_iterator_impl const & other) const {
  32. return std::get<0>(other._data) - std::get<0>(_data);
  33. }
  34. private:
  35. std::tuple<Ts...> _data;
  36. };
  37. }
  38. namespace iterator {
  39. template <typename... Ts>
  40. using index_sequence = decltype(std::make_index_sequence<sizeof...(Ts)>{});
  41. template <typename... Ts>
  42. using zip_impl =
  43. detail::zip_iterator_impl<std::tuple<Ts...>, index_sequence<Ts...>>;
  44. template <typename... Iterators>
  45. constexpr auto
  46. zip_category_for = std::min({detail::category_for_v<Iterators>...});
  47. template <typename... Iters>
  48. class zip_iterator
  49. : public zip_impl<Iters...>,
  50. public facade<zip_iterator<Iters...>, zip_category_for<Iters...>> {
  51. public:
  52. zip_iterator() = default;
  53. zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
  54. };
  55. template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
  56. }
  57. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::zip_iterator);