Index: llvm/trunk/include/llvm/ADT/STLExtras.h =================================================================== --- llvm/trunk/include/llvm/ADT/STLExtras.h +++ llvm/trunk/include/llvm/ADT/STLExtras.h @@ -341,6 +341,95 @@ FilterIteratorT(std::end(std::forward(Range)))); } +// forward declarations required by zip_shortest/zip_first +template +bool all_of(R &&range, UnaryPredicate &&P); + +template struct index_sequence; + +template struct index_sequence_for; + +namespace detail { +template class zip_first { +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 zip_first &other) const { + return std::get<0>(iterators) != std::get<0>(other.iterators); + } + zip_first(Iters &&... ts) : iterators(std::forward(ts)...) {} +}; + +template class zip_shortest : public zip_first { + template + bool test(const zip_first &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{}); + } + zip_shortest(Iters &&... ts) + : zip_first(std::forward(ts)...) {} +}; + +template