Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -341,6 +341,107 @@ FilterIteratorT(std::end(std::forward(Range)))); } +// forward declarations required by ZipShortest/ZipFirst +template +bool all_of(R &&range, UnaryPredicate &&P); + +template struct index_sequence; + +template struct index_sequence_for; + +template struct build_index_impl; + +namespace detail { +template +auto apply_tuple_impl(F &&f, Tuple &&t, index_sequence) + -> decltype(std::forward(f)(std::get(std::forward(t))...)); +} + +template +auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( + std::forward(f), std::forward(t), + build_index_impl< + std::tuple_size::type>::value>{})); + +namespace detail { +template class ZipFirst { +public: + typedef std::input_iterator_tag iterator_category; + typedef std::tuple())...> value_type; + std::tuple iterators; + +public: + value_type operator*() { + auto f = [](Iters &... args) { return value_type(*args...); }; + return apply_tuple(f, iterators); + } + + void operator++() { + auto f = [](Iters &... args) { + return decltype(iterators)(std::next(args)...); + }; + iterators = apply_tuple(f, iterators); + } + + 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