Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -356,65 +356,93 @@ template struct index_sequence_for; namespace detail { -template class zip_first { -public: - typedef std::input_iterator_tag iterator_category; - typedef std::tuple())...> value_type; +template +using zip_traits = + iterator_facade_base())...>, + std::ptrdiff_t, + std::tuple())...> *, + std::tuple())...>>; + +template +struct zip_common : public zip_traits { + using value_type = typename zip_traits::value_type; + std::tuple iterators; -private: - template value_type deres(index_sequence) { +protected: + template value_type deref(index_sequence) const { return value_type(*std::get(iterators)...); } - template decltype(iterators) tup_inc(index_sequence) { + template + decltype(iterators) tup_inc(index_sequence) const { return std::tuple(std::next(std::get(iterators))...); } public: - value_type operator*() { return deres(index_sequence_for{}); } + zip_common(Iters &&... ts) : iterators(std::forward(ts)...) {} - void operator++() { iterators = tup_inc(index_sequence_for{}); } + value_type operator*() { return deref(index_sequence_for{}); } - bool operator!=(const zip_first &other) const { - return std::get<0>(iterators) != std::get<0>(other.iterators); + const value_type operator*() const { + return deref(index_sequence_for{}); } - zip_first(Iters &&... ts) : iterators(std::forward(ts)...) {} + + ZipType &operator++() { + iterators = tup_inc(index_sequence_for{}); + return *reinterpret_cast(this); + } +}; + +template +struct zip_first : public zip_common, Iters...> { + using Base = zip_common, Iters...>; + bool operator==(const zip_first &other) const { + return std::get<0>(this->iterators) == std::get<0>(other.iterators); + } + zip_first(Iters &&... ts) : Base(std::forward(ts)...) {} }; -template class zip_shortest : public zip_first { +template +class zip_shortest : public zip_common, Iters...> { template - bool test(const zip_first &other, index_sequence) const { + bool test(const zip_shortest &other, index_sequence) const { return all_of(std::initializer_list{std::get(this->iterators) != std::get(other.iterators)...}, identity{}); } public: - bool operator!=(const zip_first &other) const { - return test(other, index_sequence_for{}); + using Base = zip_common, Iters...>; + bool operator==(const zip_shortest &other) const { + return !test(other, index_sequence_for{}); } - zip_shortest(Iters &&... ts) - : zip_first(std::forward(ts)...) {} + zip_shortest(Iters &&... ts) : Base(std::forward(ts)...) {} }; template