Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -235,6 +235,96 @@ llvm::make_reverse_iterator(std::begin(C))); } +namespace detail { +template struct NatList { + using eval = typename NatList::eval; +}; + +template struct NatList<0, Ns...> { + using eval = NatList; +}; + +template class ZipFirst { +public: + typedef typename NatList::eval nat_list; + typedef std::input_iterator_tag iterator_category; + typedef std::tuple())...> value_type; + std::tuple iterators; + +private: + template value_type deres(NatList) { + return value_type(*std::get(iterators)...); + } + + template decltype(iterators) tup_inc(NatList) { + return std::tuple(std::next(std::get(iterators))...); + } + +public: + value_type operator*() { return deres(nat_list{}); } + + void operator++() { iterators = tup_inc(nat_list{}); } + + 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, NatList) const { + std::array conds = { + (std::get(this->iterators) != std::get(other.iterators))...}; + return std::all_of(conds.begin(), conds.end(), [](bool a) { return a; }); + } + +public: + bool operator!=(const ZipFirst &other) const { + return test(other, typename ZipFirst::nat_list{}); + } + ZipShortest(Iters &&... ts) + : ZipFirst(std::forward(ts)...) {} +}; + +template