Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -235,6 +235,95 @@ llvm::make_reverse_iterator(std::begin(C))); } +// forward declarations required by ZipShortest/ZipFirst +template +bool all_of(R &&range, UnaryPredicate &&P); + +template struct index_sequence; + +template struct index_sequence_for; + +namespace detail { +template class ZipFirst { +public: + typedef std::input_iterator_tag iterator_category; + typedef std::tuple())...> value_type; + std::tuple iterators; + +private: + template value_type deres(index_sequence) { + return value_type(*std::get(iterators)...); + } + + template decltype(iterators) tup_inc(index_sequence) { + return std::tuple(std::next(std::get(iterators))...); + } + +public: + value_type operator*() { return deres(index_sequence_for{}); } + + void operator++() { iterators = tup_inc(index_sequence_for{}); } + + bool operator!=(const ZipFirst &other) const { + return std::get<0>(iterators) != std::get<0>(other.iterators); + } + ZipFirst(Iters &&... ts) : iterators(std::forward(ts)...) {} +}; + +template class ZipShortest : public ZipFirst { + template + bool test(const ZipFirst &other, index_sequence) const { + return all_of(std::initializer_list{std::get(this->iterators) != + std::get(other.iterators)...}, + identity{}); + } + +public: + bool operator!=(const ZipFirst &other) const { + return test(other, index_sequence_for{}); + } + ZipShortest(Iters &&... ts) + : ZipFirst(std::forward(ts)...) {} +}; + +template