zip_iterator.hpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #pragma once
  2. #include <iterator>
  3. #include <tuple>
  4. #include "proxy.h"
  5. namespace iterator::zip {
  6. template <typename... Iters> struct impl {
  7. public:
  8. using difference_type = std::common_type_t<
  9. typename std::iterator_traits<Iters>::difference_type...>;
  10. public:
  11. std::tuple<Iters...> data;
  12. public:
  13. impl() = default;
  14. impl(Iters &&... iters) : data(iters...) {}
  15. auto operator*() const {
  16. return std::make_tuple(*std::get<Iters>(data)...);
  17. }
  18. void operator++(int) {
  19. [[maybe_unused]] auto l = {(++(std::get<Iters>(data)), 0)...};
  20. }
  21. void operator--(int) {
  22. [[maybe_unused]] auto l = {(--(std::get<Iters>(data)), 0)...};
  23. }
  24. void operator+=(difference_type d) {
  25. [[maybe_unused]] auto l = {((std::get<Iters>(data) += d), 0)...};
  26. }
  27. bool operator==(impl const & other) const { return data == other.data; }
  28. auto operator-(impl const & other) const {
  29. return std::get<0>(data) - std::get<0>(other.data);
  30. }
  31. };
  32. }
  33. namespace std {
  34. template <typename... Iters>
  35. struct iterator_traits<::iterator::zip::impl<Iters...>> {
  36. using difference_type =
  37. common_type_t<typename iterator_traits<Iters>::difference_type...>;
  38. using iterator_category =
  39. common_type_t<typename iterator_traits<Iters>::iterator_category...>;
  40. };
  41. }
  42. namespace iterator {
  43. template <typename... Iters>
  44. class zip_iterator
  45. : public proxy<zip::impl<Iters...>, zip_iterator<Iters...>> {
  46. private:
  47. using super = proxy<zip::impl<Iters...>, zip_iterator<Iters...>>;
  48. public:
  49. zip_iterator() = default;
  50. zip_iterator(Iters &&... iters) : super(std::forward<Iters>(iters)...) {}
  51. };
  52. }
  53. namespace std {
  54. template <typename... T>
  55. struct iterator_traits<::iterator::zip_iterator<T...>>
  56. : std::iterator_traits<
  57. ::iterator::facade<::iterator::zip_iterator<T...>>> {
  58. // This shouldn't need to be implemented, but for some reason my traits
  59. // are not correctly deducing here.
  60. using iterator_category =
  61. common_type_t<typename iterator_traits<T>::iterator_category...>;
  62. };
  63. }
  64. template <typename... Is>
  65. iterator::zip_iterator<Is...> make_zip_iterator(Is &&... iters) {
  66. return {std::forward<Is>(iters)...};
  67. }