Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -235,6 +235,109 @@ llvm::make_reverse_iterator(std::begin(C))); } +// NatList :: [Nat] +template struct NatList {}; + +template struct Cons {}; + +template struct Cons, NatList> { + using eval = NatList; +}; + +template struct Cons, T> { + using eval = Cons, typename T::eval>; +}; + +template struct BuildNatList { + using eval = typename Cons, + typename BuildNatList::eval>::eval; +}; + +template struct BuildNatList { + using eval = NatList; +}; + +template class ZipFirst { + public: + typedef typename BuildNatList<0, sizeof...(Iters)-1>::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