Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions llvm/include/llvm/ADT/STLExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,11 @@ auto sum_of(R &&Range, E Init = E{0}) {
return accumulate(std::forward<R>(Range), std::move(Init));
}

/// Returns a range where each value of `R` is static_cast to `T`
template <typename T, typename R> auto static_cast_to(R &&Range) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea makes sense but I wonder if we could pick a more descriptive function name, similar to other range functions

Copy link
Member

@kuhar kuhar Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One alternative would be not to add a range function and instead lift static cast to a function object like we did for llvm::IsaPred<T>. This way we can support variants based on dyn_cast/dyn_cast_if_present/cast.

I think that's a more general solution that composes with other functions like map_to_vector

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would the usage look like?

Copy link
Member

@kuhar kuhar Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map_range(Foo, StaticCastTo<unsigned>)
map_range(Bar, DynCastTo<IntegerAttr>)
map_to_vector(Baz, CastTo<FloatType>)

return map_range(Range, [](const auto &V) { return static_cast<T>(V); });
Copy link
Contributor

@zwuis zwuis Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[](auto &V) -> decltype(auto) { return static_cast<T>(V); }

Perhaps -> decltype(auto) is needed to allow returning reference.

}

/// Returns the product of all values in `Range` with `Init` initial value.
/// The default initial value is 1.
template <typename R, typename E = detail::ValueOfRange<R>>
Expand Down
7 changes: 7 additions & 0 deletions llvm/unittests/ADT/STLExtrasTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,13 @@ TEST(STLExtrasTest, SumOf) {
EXPECT_EQ(sum_of(V3), 3.0f);
}

TEST(STLExtrasTest, StaticCastTo) {
std::vector<int32_t> R{1, 2, 3};
EXPECT_TRUE(all_of(R, [](auto V) { return sizeof(V) == sizeof(int32_t); }));
EXPECT_TRUE(all_of(static_cast_to<int64_t>(R),
[](auto V) { return sizeof(V) == sizeof(int64_t); }));
}

TEST(STLExtrasTest, ProductOf) {
EXPECT_EQ(product_of(std::vector<int>()), 1);
EXPECT_EQ(product_of(std::vector<int>(), 0), 0);
Expand Down