zip_iterator.h 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  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. requires(std::bidirectional_iterator<Ts> && ...)
  24. {
  25. [[maybe_unused]] auto l = {((--std::get<Is>(_data)), 0)...};
  26. }
  27. void advance(difference_type d)
  28. requires(std::random_access_iterator<Ts> && ...)
  29. {
  30. [[maybe_unused]] auto l = {((std::get<Is>(_data) += d), 0)...};
  31. }
  32. bool equal_to(zip_iterator_impl const & other) const {
  33. return _data == other._data;
  34. }
  35. auto distance_to(zip_iterator_impl const & other) const
  36. requires(std::random_access_iterator<Ts> && ...)
  37. {
  38. return std::get<0>(other._data) - std::get<0>(_data);
  39. }
  40. private:
  41. std::tuple<Ts...> _data;
  42. };
  43. }
  44. namespace iterator {
  45. template <typename... Ts>
  46. using index_sequence = decltype(std::make_index_sequence<sizeof...(Ts)>{});
  47. template <typename... Ts>
  48. using zip_impl =
  49. detail::zip_iterator_impl<std::tuple<Ts...>, index_sequence<Ts...>>;
  50. template <typename... Iters>
  51. class zip_iterator : public zip_impl<Iters...>,
  52. public facade<zip_iterator<Iters...>> {
  53. public:
  54. zip_iterator() = default;
  55. zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
  56. };
  57. template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
  58. }