#pragma once #include #include #include "facade.h" namespace iterator::detail { template class zip_iterator_impl; template class zip_iterator_impl, std::index_sequence> { public: using difference_type = std::common_type_t::difference_type...>; public: zip_iterator_impl() = default; zip_iterator_impl(Ts... iters) : _data(iters...) {} auto dereference() const { return std::forward_as_tuple(*std::get(_data)...); } void increment() { [[maybe_unused]] auto l = {((++std::get(_data)), 0)...}; } void decrement() { [[maybe_unused]] auto l = {((++std::get(_data)), 0)...}; } void advance(difference_type d) { [[maybe_unused]] auto l = {((std::get(_data) += d), 0)...}; } bool equal_to(zip_iterator_impl const & other) const { return _data == other._data; } auto distance_to(zip_iterator_impl const & other) const { return std::get<0>(other._data) - std::get<0>(_data); } private: std::tuple _data; }; } namespace iterator { template using index_sequence = decltype(std::make_index_sequence{}); template using zip_impl = detail::zip_iterator_impl, index_sequence>; template class zip_iterator : public zip_impl, public facade> { public: zip_iterator() = default; zip_iterator(Iters... iters) : zip_impl(iters...) {} }; template zip_iterator(It...) -> zip_iterator; } template struct std::iterator_traits<::iterator::zip_iterator> : std::iterator_traits<::iterator::facade<::iterator::zip_iterator>> { // This shouldn't need to be implemented, but for some reason my traits // are not correctly deducing here. using iterator_category = common_type_t::iterator_category...>; };