zip_iterator.hpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  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 { return _data == other._data; }
  28. auto distance_to(zip_iterator_impl const & other) const {
  29. return std::get<0>(other._data) - std::get<0>(_data);
  30. }
  31. private:
  32. std::tuple<Ts...> _data;
  33. };
  34. }
  35. namespace iterator {
  36. template <typename... Ts>
  37. using index_sequence = decltype(std::make_index_sequence<sizeof...(Ts)>{});
  38. template <typename... Ts>
  39. using zip_impl = detail::zip_iterator_impl<std::tuple<Ts...>, index_sequence<Ts...>>;
  40. template <typename... Iters>
  41. class zip_iterator : public zip_impl<Iters...>, public facade<zip_iterator<Iters...>> {
  42. public:
  43. zip_iterator() = default;
  44. zip_iterator(Iters... iters) : zip_impl<Iters...>(iters...) {}
  45. };
  46. template <typename... It> zip_iterator(It...) -> zip_iterator<It...>;
  47. }
  48. template <typename... T>
  49. struct std::iterator_traits<::iterator::zip_iterator<T...>>
  50. : std::iterator_traits<::iterator::facade<::iterator::zip_iterator<T...>>> {
  51. // This shouldn't need to be implemented, but for some reason my traits
  52. // are not correctly deducing here.
  53. using iterator_category =
  54. common_type_t<typename iterator_traits<T>::iterator_category...>;
  55. };
  56. template <typename... Is>
  57. iterator::zip_iterator<Is...> make_zip_iterator(Is &&... iters) {
  58. return {std::forward<Is>(iters)...};
  59. }