Skip to content

Commit 9a5fa30

Browse files
authored
[ADT] Add llvm::reverse_conditionally() iterator (#171040)
This patch adds a simple iterator range that allows conditionally iterating a collection in reverse. It works with any collection supported by `llvm::reverse(Collection)`. ``` void foo(bool Reverse, std::vector<int>& C) { for (int I : reverse_conditionally(C, Reverse)) { // ... } } ```
1 parent 886f54a commit 9a5fa30

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

llvm/include/llvm/ADT/STLExtras.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,18 @@ template <typename ContainerTy> auto make_second_range(ContainerTy &&c) {
14151415
});
14161416
}
14171417

1418+
/// Return a range that conditionally reverses \p C. The collection is iterated
1419+
/// in reverse if \p ShouldReverse is true (otherwise, it is iterated forwards).
1420+
template <typename ContainerTy>
1421+
[[nodiscard]] auto reverse_conditionally(ContainerTy &&C, bool ShouldReverse) {
1422+
using IterTy = detail::IterOfRange<ContainerTy>;
1423+
using ReferenceTy = typename std::iterator_traits<IterTy>::reference;
1424+
return map_range(zip_equal(reverse(C), C),
1425+
[ShouldReverse](auto I) -> ReferenceTy {
1426+
return ShouldReverse ? std::get<0>(I) : std::get<1>(I);
1427+
});
1428+
}
1429+
14181430
//===----------------------------------------------------------------------===//
14191431
// Extra additions to <utility>
14201432
//===----------------------------------------------------------------------===//

llvm/unittests/ADT/STLExtrasTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,30 @@ TEST(STLExtrasTest, ProductOf) {
16931693
EXPECT_EQ(product_of(V3), 2.0f);
16941694
}
16951695

1696+
TEST(STLExtrasTest, ReverseConditionally) {
1697+
std::vector<char> foo = {'a', 'b', 'c'};
1698+
1699+
// Test backwards.
1700+
std::vector<char> ReverseResults;
1701+
for (char Value : llvm::reverse_conditionally(foo, /*ShouldReverse=*/true)) {
1702+
ReverseResults.emplace_back(Value);
1703+
}
1704+
EXPECT_THAT(ReverseResults, ElementsAre('c', 'b', 'a'));
1705+
1706+
// Test forwards.
1707+
std::vector<char> ForwardResults;
1708+
for (char Value : llvm::reverse_conditionally(foo, /*ShouldReverse=*/false)) {
1709+
ForwardResults.emplace_back(Value);
1710+
}
1711+
EXPECT_THAT(ForwardResults, ElementsAre('a', 'b', 'c'));
1712+
1713+
// Test modifying collection.
1714+
for (char &Value : llvm::reverse_conditionally(foo, /*ShouldReverse=*/true)) {
1715+
++Value;
1716+
}
1717+
EXPECT_THAT(foo, ElementsAre('b', 'c', 'd'));
1718+
}
1719+
16961720
struct Foo;
16971721
struct Bar {};
16981722

0 commit comments

Comments
 (0)