#ifndef ITER_ZIP_HPP_ #define ITER_ZIP_HPP_ #include "internal/iterbase.hpp" #include #include #include #include namespace iter { namespace impl { template class Zipped; template Zipped zip_impl(TupleType&&, std::index_sequence); } template auto zip(Containers&&... containers); } template class iter::impl::Zipped { private: TupleType containers; friend Zipped iter::impl::zip_impl( TupleType&&, std::index_sequence); using ZipIterDeref = iterator_deref_tuple; Zipped(TupleType&& in_containers) : containers(std::move(in_containers)) {} public: Zipped(Zipped&&) = default; class Iterator : public std::iterator { private: iterator_tuple_type iters; public: Iterator(iterator_tuple_type&& its) : iters(std::move(its)) {} Iterator& operator++() { absorb(++std::get(this->iters)...); return *this; } Iterator operator++(int) { auto ret = *this; ++*this; return ret; } bool operator!=(const Iterator& other) const { if (sizeof...(Is) == 0) return false; bool results[] = { true, (std::get(this->iters) != std::get(other.iters))...}; return std::all_of( std::begin(results), std::end(results), [](bool b) { return b; }); } bool operator==(const Iterator& other) const { return !(*this != other); } ZipIterDeref operator*() { return ZipIterDeref{(*std::get(this->iters))...}; } auto operator -> () -> ArrowProxy { return {**this}; } }; Iterator begin() { return {iterator_tuple_type{ std::begin(std::get(this->containers))...}}; } Iterator end() { return {iterator_tuple_type{ std::end(std::get(this->containers))...}}; } }; template iter::impl::Zipped iter::impl::zip_impl( TupleType&& in_containers, std::index_sequence) { return {std::move(in_containers)}; } template auto iter::zip(Containers&&... containers) { return impl::zip_impl( std::tuple{std::forward(containers)...}, std::index_sequence_for{}); } #endif