如何将投影与 C++20 范围内的变换结合起来
How to combine projections with transform in C++20 ranges
C++20 ranges::sort
支持投影,这很好,但我想做更复杂的事情,特别是对对投影成员进行操作的函数结果进行排序。
对于函数调用,我尝试了转换,然后对该视图进行排序,但 C++20 排序似乎不适用于视图,这 解释了原因(对于 range-v3)。
换句话说,我可以不用 lambda/functor 写 this 吗?
struct S{
int val;
};
int origin = 47;
// assume we can not change Distance to take S
int Distance(int val){
return std::abs(val - origin);
}
void my_sort(std::vector<S> ss) {
std::ranges::sort(ss, std::greater<>{}, [](const S& s){
return Distance(s.val);
});
}
如果您的 S
只有一名成员,您可以使用 views::transform
:
void my_sort(std::vector<S> ss) {
std::ranges::sort(
ss | std::views::transform(&S::val), std::ranges::greater{}, Distance
);
}
您似乎想要函数组合:
void my_sort(std::vector<S>& ss) {
std::ranges::sort(ss, std::greater<>{}, compose(Distance, &S::val));
}
compose(f, g)(x)
做 f(g(x))
。 Boost.Hof 有一个 compose
,某处也有一个在 range-v3 中。不过标准库中没有。
For function call I tried the transform and then sort that view,
sort(r, less(), f)
和sort(r | transform(f), less())
有很大区别:前者用函数f
作为排序关键字对r
进行排序,后者对专门转换值。展示差异的具体示例:
struct X {
int i;
int j;
};
vector<X> xs = {X{1, 2}, X{2, 1}, X{0, 7}};
// this would give you (0, 7), (1, 2), (2, 1)
// because we're sorting by the i
ranges::sort(xs, less(), &X::i);
// this would have given you (0, 2), (1, 1), (2, 7)
// because we're sorting the i's independently
ranges::sort(xs | views::transform(&X::i), less());
C++20 ranges::sort
支持投影,这很好,但我想做更复杂的事情,特别是对对投影成员进行操作的函数结果进行排序。
对于函数调用,我尝试了转换,然后对该视图进行排序,但 C++20 排序似乎不适用于视图,这
换句话说,我可以不用 lambda/functor 写 this 吗?
struct S{
int val;
};
int origin = 47;
// assume we can not change Distance to take S
int Distance(int val){
return std::abs(val - origin);
}
void my_sort(std::vector<S> ss) {
std::ranges::sort(ss, std::greater<>{}, [](const S& s){
return Distance(s.val);
});
}
如果您的 S
只有一名成员,您可以使用 views::transform
:
void my_sort(std::vector<S> ss) {
std::ranges::sort(
ss | std::views::transform(&S::val), std::ranges::greater{}, Distance
);
}
您似乎想要函数组合:
void my_sort(std::vector<S>& ss) {
std::ranges::sort(ss, std::greater<>{}, compose(Distance, &S::val));
}
compose(f, g)(x)
做 f(g(x))
。 Boost.Hof 有一个 compose
,某处也有一个在 range-v3 中。不过标准库中没有。
For function call I tried the transform and then sort that view,
sort(r, less(), f)
和sort(r | transform(f), less())
有很大区别:前者用函数f
作为排序关键字对r
进行排序,后者对专门转换值。展示差异的具体示例:
struct X {
int i;
int j;
};
vector<X> xs = {X{1, 2}, X{2, 1}, X{0, 7}};
// this would give you (0, 7), (1, 2), (2, 1)
// because we're sorting by the i
ranges::sort(xs, less(), &X::i);
// this would have given you (0, 2), (1, 1), (2, 7)
// because we're sorting the i's independently
ranges::sort(xs | views::transform(&X::i), less());