zip_iterator.h 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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() requires(std::bidirectional_iterator<Ts> && ...) {
  23. [[maybe_unused]] auto l = {((--std::get<Is>(_data)), 0)...};
  24. }
  25. void advance(difference_type d) requires(std::random_access_iterator<Ts> && ...) {
  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 requires(std::random_access_iterator<Ts> && ...) {
  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... Iters>
  45. class zip_iterator
  46. : public zip_impl<Iters...>,
  47. public facade<zip_iterator<Iters...>> {
  48. public:
  49. zip_iterator() = default;
  50. zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
  51. };
  52. template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
  53. }
  54. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::zip_iterator);