#pragma once #include #include #include #include namespace iterator::detail { template class ZipImpl; template class ZipImpl, std::index_sequence> { public: using difference_type = std::common_type_t::difference_type...>; public: ZipImpl() = default; ZipImpl(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() requires(std::bidirectional_iterator && ...) { [[maybe_unused]] auto l = {((--std::get(_data)), 0)...}; } void advance(difference_type d) requires(std::random_access_iterator && ...) { [[maybe_unused]] auto l = {((std::get(_data) += d), 0)...}; } bool equal_to(ZipImpl const & other) const { return _data == other._data; } auto distance_to(ZipImpl const & other) const requires(std::random_access_iterator && ...) { 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 ZipImpl = detail::ZipImpl, index_sequence>; template class ZipIterator : public ZipImpl, public Facade> { public: ZipIterator() = default; ZipIterator(Iters... iters) : ZipImpl(iters...) {} }; template ZipIterator(It...) -> ZipIterator; }