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 @@ -268,6 +268,13 @@ adl_end(RangeOrContainer)); } +/// Return a range covering \p RangeOrContainer with the last N elements +/// excluded. +template auto drop_end(T &&RangeOrContainer, size_t N = 1) { + return make_range(adl_begin(RangeOrContainer), + std::prev(adl_end(RangeOrContainer), N)); +} + // mapped_iterator - This is a simple iterator adapter that causes a function to // be applied whenever operator* is invoked on the iterator. 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 @@ -457,6 +457,30 @@ EXPECT_EQ(i, 5); } +TEST(STLExtrasTest, DropEndTest) { + SmallVector vec{0, 1, 2, 3, 4}; + + for (int n = 0; n < 5; ++n) { + int i = 0; + for (auto &v : drop_end(vec, n)) { + EXPECT_EQ(v, i); + i += 1; + } + EXPECT_EQ(i, 5 - n); + } +} + +TEST(STLExtrasTest, DropEndDefaultTest) { + SmallVector vec{0, 1, 2, 3, 4}; + + int i = 0; + for (auto &v : drop_end(vec)) { + EXPECT_EQ(v, i); + i += 1; + } + EXPECT_EQ(i, 4); +} + TEST(STLExtrasTest, EarlyIncrementTest) { std::list L = {1, 2, 3, 4};