zip_iterator.hpp 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #pragma once
  2. #include <iterator>
  3. #include <tuple>
  4. #include "facade.h"
  5. namespace iterator::detail {
  6. template <typename Tuple, typename IS> class zip_iterator_impl;
  7. template <typename... Ts, size_t... Is>
  8. class zip_iterator_impl<std::tuple<Ts...>, std::index_sequence<Is...>> {
  9. public:
  10. using difference_type =
  11. std::common_type_t<typename std::iterator_traits<Ts>::difference_type...>;
  12. public:
  13. zip_iterator_impl() = default;
  14. zip_iterator_impl(Ts... iters) : _data(iters...) {}
  15. auto dereference() const {
  16. return std::forward_as_tuple(*std::get<Is>(_data)...);
  17. }
  18. void increment() {
  19. [[maybe_unused]] auto l = {((++std::get<Is>(_data)), 0)...};
  20. }
  21. void decrement() {
  22. [[maybe_unused]] auto l = {((++std::get<Is>(_data)), 0)...};
  23. }
  24. void advance(difference_type d) {
  25. [[maybe_unused]] auto l = {((std::get<Is>(_data) += d), 0)...};
  26. }
  27. bool equal_to(zip_iterator_impl const & other) const {
  28. return _data == other._data;
  29. }
  30. auto distance_to(zip_iterator_impl const & other) const {
  31. return std::get<0>(other._data) - std::get<0>(_data);
  32. }
  33. private:
  34. std::tuple<Ts...> _data;
  35. };
  36. }
  37. namespace iterator {
  38. template <typename... Ts>
  39. using index_sequence = decltype(std::make_index_sequence<sizeof...(Ts)>{});
  40. template <typename... Ts>
  41. using zip_impl =
  42. detail::zip_iterator_impl<std::tuple<Ts...>, index_sequence<Ts...>>;
  43. template <typename... Iters>
  44. class zip_iterator : public zip_impl<Iters...>,
  45. public facade<zip_iterator<Iters...>> {
  46. public:
  47. zip_iterator() = default;
  48. zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
  49. };
  50. template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
  51. }
  52. template <typename... T>
  53. struct std::iterator_traits<::iterator::zip_iterator<T...>>
  54. : std::iterator_traits<::iterator::facade<::iterator::zip_iterator<T...>>> {
  55. // This shouldn't need to be implemented, but for some reason my traits
  56. // are not correctly deducing here.
  57. using iterator_category =
  58. common_type_t<typename iterator_traits<T>::iterator_category...>;
  59. };