C++ 范围是否支持视图中的投影?

NoS*_*tAl 6 c++ c++20 std-ranges

我知道sort范围内的算法(例如)支持投影,但在我看来,没有办法为视图获得该功能......我对吗?

作为示例,请考虑以下工作代码

#include <algorithm>
#include <ranges>
#include <vector>
#include <iostream>

enum Color {
   Red,
   Green,
   Blue
}; 
struct Cat {
   int age;
   Color color;
};

int main() {
    std::vector<Cat> cats{{.age = 10,.color=Color::Red}, {.age = 20,.color=Color::Blue}, {.age = 30,.color=Color::Green}};
    auto is_red = [](const auto& cat) {return cat.color == Color::Red;};
    for (const auto& cat: cats | std::views::filter(is_red)) {
        std::cout << cat.age << std::endl; 
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法删除 lambda 并执行以下操作:

for (const auto& cat: cats | std::views::filter(&Cat::color, Color::Red) {
Run Code Online (Sandbox Code Playgroud)

注意:我的问题是成员变量投影,但显然在实际代码中也需要成员函数调用。

Bar*_*rry 5

C++ 范围是否支持视图中的投影?

否(尽管 range-v3 做了)。

有没有办法删除 lambda 并执行以下操作:

std::views::filter(&Cat::color, Color::Red)
Run Code Online (Sandbox Code Playgroud)

无论如何,这不会真正与投影一起工作。本来是:

std::views::filter(&Cat::color, Color::Red)
Run Code Online (Sandbox Code Playgroud)

如果你有一个equals返回谓词的,你可以减少这个:

filter([](Color c){ return c == Color::Red; }, &Cat::color)
Run Code Online (Sandbox Code Playgroud)

但是向算法添加投影是不必要的。您始终可以手动提供投影。使用Boost.Hof适当命名的proj函数适配器,它满足proj(p, f)(xs...) == f(p(xs)...)(即我们在将p它们传递到 之前应用每个参数f):

filter(equals(Color::Red), &Cat::color)
Run Code Online (Sandbox Code Playgroud)

或者,更短:

filter(proj(&Cat::color, [](Color c){ return c == Color::Red; }))
Run Code Online (Sandbox Code Playgroud)

演示


即使在range-v3 实现中,也没有remove_if_view明确支持投影。这是手动进行投影的重载为您组合谓词为compose(pred, proj). 在 range-v3 中,compose(f, g)(xs...)可以表示f(g(xs...))f(g(xs)...)取决于如何g调用。所以在这种情况下,它是一个投影而不是函数组合。在 Boost.Hof 中,两种情况都有不同的composeproj适配器。