diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1697,6 +1697,26 @@ std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); } +/// Compare two ranges using the provided predicate, returns true if all +/// elements satisfy the predicate and false otherwise. None is returned if the +/// ranges' size mismatch. +template +Optional all_of_zip(R &&Lhs, U &&Rhs, Predicate P) { + auto Literator = adl_begin(Lhs); + auto Riterator = adl_begin(Rhs); + auto Lend = adl_end(Lhs); + auto Rend = adl_end(Rhs); + while (Literator != Lend && Riterator != Rend) { + if (!P(*Literator, *Riterator)) + return false; + ++Literator; + ++Riterator; + } + if (Literator != Lend || Riterator != Rend) + return None; + return true; +} + /// Provide a container algorithm similar to C++ Library Fundamentals v2's /// `erase_if` which is equivalent to: /// diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -876,4 +876,13 @@ EXPECT_EQ(2, Destructors); } +TEST(STLExtrasTest, AllOfZip) { + std::vector v1 = {0, 4, 2, 1}; + std::vector v2 = {1, 4, 3, 6}; + EXPECT_TRUE(*all_of_zip(v1, v2, [](int L, int R) { return L <= R; })); + EXPECT_FALSE(*all_of_zip(v1, v2, [](int L, int R) { return L < R; })); + std::vector v3 = {1, 4}; + EXPECT_EQ(None, all_of_zip(v1, v3, [](int L, int R) { return true; })); +} + } // namespace