[ADT] Allow member pointers in map_range and map_to_vector (#181154)
This is for when all we need is to access a field or call a getter: no need to write a lambda just to extract these. Assisted-by: claude
This commit is contained in:
parent
6f51f8e0f9
commit
1f404ec04d
@ -219,13 +219,13 @@ public:
|
||||
template <typename... Pn,
|
||||
std::enable_if_t<std::is_invocable_v<T, Pn...>, int> = 0>
|
||||
decltype(auto) operator()(Pn &&...Params) {
|
||||
return (*Obj)(std::forward<Pn>(Params)...);
|
||||
return std::invoke(*Obj, std::forward<Pn>(Params)...);
|
||||
}
|
||||
|
||||
template <typename... Pn,
|
||||
std::enable_if_t<std::is_invocable_v<T const, Pn...>, int> = 0>
|
||||
decltype(auto) operator()(Pn &&...Params) const {
|
||||
return (*Obj)(std::forward<Pn>(Params)...);
|
||||
return std::invoke(*Obj, std::forward<Pn>(Params)...);
|
||||
}
|
||||
|
||||
bool valid() const { return Obj != std::nullopt; }
|
||||
@ -330,7 +330,7 @@ template <typename T> auto drop_end(T &&RangeOrContainer, size_t N = 1) {
|
||||
|
||||
template <typename ItTy, typename FuncTy,
|
||||
typename ReferenceTy =
|
||||
decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
|
||||
std::invoke_result_t<FuncTy, decltype(*std::declval<ItTy>())>>
|
||||
class mapped_iterator
|
||||
: public iterator_adaptor_base<
|
||||
mapped_iterator<ItTy, FuncTy>, ItTy,
|
||||
@ -360,6 +360,8 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
|
||||
return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
|
||||
}
|
||||
|
||||
/// Return a range that applies \p F to the elements of \p C. \p F can be a
|
||||
/// function, lambda, or member pointer.
|
||||
template <class ContainerTy, class FuncTy>
|
||||
auto map_range(ContainerTy &&C, FuncTy F) {
|
||||
return make_range(map_iterator(adl_begin(C), F), map_iterator(adl_end(C), F));
|
||||
|
||||
@ -34,6 +34,7 @@ auto filter_to_vector(ContainerTy &&C, PredicateFn &&Pred) {
|
||||
}
|
||||
|
||||
/// Map a range to a SmallVector with element types deduced from the mapping.
|
||||
/// \p F can be a function, lambda, or member pointer.
|
||||
template <unsigned Size, class ContainerTy, class FuncTy>
|
||||
auto map_to_vector(ContainerTy &&C, FuncTy &&F) {
|
||||
return to_vector<Size>(
|
||||
@ -41,6 +42,7 @@ auto map_to_vector(ContainerTy &&C, FuncTy &&F) {
|
||||
}
|
||||
|
||||
/// Map a range to a SmallVector with element types deduced from the mapping.
|
||||
/// \p F can be a function, lambda, or member pointer.
|
||||
template <class ContainerTy, class FuncTy>
|
||||
auto map_to_vector(ContainerTy &&C, FuncTy &&F) {
|
||||
return to_vector(
|
||||
|
||||
@ -835,6 +835,22 @@ TEST(STLExtrasTest, DropEndDefaultTest) {
|
||||
EXPECT_THAT(drop_end(vec), ElementsAre(0, 1, 2, 3));
|
||||
}
|
||||
|
||||
TEST(STLExtrasTest, CallableMemberPointer) {
|
||||
struct S {
|
||||
int X;
|
||||
int getX() const { return X; }
|
||||
};
|
||||
S Obj{42};
|
||||
|
||||
// Data member pointer.
|
||||
callable_detail::Callable<int S::*> DataMember(&S::X);
|
||||
EXPECT_EQ(DataMember(Obj), 42);
|
||||
|
||||
// Member function pointer.
|
||||
callable_detail::Callable<int (S::*)() const> MemFn(&S::getX);
|
||||
EXPECT_EQ(MemFn(Obj), 42);
|
||||
}
|
||||
|
||||
TEST(STLExtrasTest, MapRangeTest) {
|
||||
SmallVector<int, 5> Vec{0, 1, 2};
|
||||
EXPECT_THAT(map_range(Vec, [](int V) { return V + 1; }),
|
||||
@ -845,6 +861,17 @@ TEST(STLExtrasTest, MapRangeTest) {
|
||||
some_namespace::some_struct S;
|
||||
S.data = {3, 4, 5};
|
||||
EXPECT_THAT(map_range(S, [](int V) { return V * 2; }), ElementsAre(6, 8, 10));
|
||||
|
||||
// Pointer to data member.
|
||||
struct MapRangeStruct {
|
||||
int X;
|
||||
int getX() const { return X; }
|
||||
};
|
||||
std::vector<MapRangeStruct> Structs = {{1}, {2}, {3}};
|
||||
EXPECT_THAT(map_range(Structs, &MapRangeStruct::X), ElementsAre(1, 2, 3));
|
||||
|
||||
// Pointer to member function.
|
||||
EXPECT_THAT(map_range(Structs, &MapRangeStruct::getX), ElementsAre(1, 2, 3));
|
||||
}
|
||||
|
||||
TEST(STLExtrasTest, EarlyIncrementTest) {
|
||||
|
||||
@ -22,6 +22,25 @@ using testing::ElementsAre;
|
||||
namespace llvm {
|
||||
namespace {
|
||||
|
||||
TEST(SmallVectorExtrasTest, MapToVector) {
|
||||
std::vector<int> Numbers = {1, 2, 3};
|
||||
auto Doubled = map_to_vector(Numbers, [](int X) { return X * 2; });
|
||||
EXPECT_THAT(Doubled, ElementsAre(2, 4, 6));
|
||||
|
||||
// Member pointer.
|
||||
struct MapToVectorStruct {
|
||||
int X;
|
||||
int getX() const { return X; }
|
||||
};
|
||||
std::vector<MapToVectorStruct> Structs = {{1}, {2}, {3}};
|
||||
EXPECT_THAT(map_to_vector(Structs, &MapToVectorStruct::X),
|
||||
ElementsAre(1, 2, 3));
|
||||
|
||||
// Member function pointer.
|
||||
EXPECT_THAT(map_to_vector(Structs, &MapToVectorStruct::getX),
|
||||
ElementsAre(1, 2, 3));
|
||||
}
|
||||
|
||||
TEST(SmallVectorExtrasTest, FilterToVector) {
|
||||
std::vector<int> Numbers = {0, 1, 2, 3, 4};
|
||||
auto Odd = filter_to_vector<2>(Numbers, [](int X) { return (X % 2) != 0; });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user