在管道之前应用投影以查看或操作

Apply projection prior to piping to view or action

我想在将范围输送到动作或视图之前应用投影。考虑以下示例:

#include <iostream>
#include <range/v3/view/map.hpp>
#include <range/v3/action/sort.hpp>
#include <range/v3/algorithm/for_each.hpp>

int main()
{
    std::vector<std::string> strings{"1.2","100.2","11.2","0.2","2.2"};
    ranges::for_each(strings, [](const auto& str) { std::cout << str << std::endl; });
    
    strings | ranges::views::all | ranges::actions::sort;
    
    std::cout << std::endl;
    ranges::for_each(strings, [](const auto& str) { std::cout << str << std::endl; });

    return 0;
}

假设我希望在排序之前将字符串转换为双精度值。使用功能方法,这是可能的:

strings |= ranges::actions::sort(std::less{}, [](const auto& str) { return std::stod(str); });

但是我想知道是否有一种管道格式允许这样做,它将此投影应用于所有以下操作,例如:

strings | ranges::views::projection([](const auto&str ) { return std::stod(str); }) | ranges::actions::sort;

请注意,使用 ranges::views::transform 不起作用,因为它会创建一个新范围而不是投影。

我也不确定是否有使用 strings | ranges::views::all | ranges::actions::sort 而不是 range-v3 文档中推荐的 strings |= ranges::actions::sort 的警告。

更新(2021.01.26):

对投影视图执行操作可能会造成混淆。例如。想象一个带有签名 int&(std::pair<int, int>&) / int&&(std::pair<int, int>&&) 的投影函数,return 是一对中的第一个分量,将该投影应用于 std::pair<int, int> 的范围。如果我们 filter 会发生什么?

  • 它应该 return 范围 int 因为我们传递给它的范围是 int.
  • 它也应该return一个std::pair<int, int>的范围,因为我们真的要过滤std::pair<int, int>的基础范围。

但是它不知道我们想要哪个。

所以这次把projection当成range上的独立操作好像不太合适,如果projection操作是filter的可选参数,反而更清楚或排序。


旧答案(2021.01.15):

用投影实现排序效率低下,也许这就是为什么不提供它的原因。您必须显式存储投影结果:
c++ - 为什么不能在 range-v3 中对范围进行排序? - 堆栈溢出

标准版说投影的复杂度是(N·log(N))(所以在排序前投影元素存储起来可能会更快):
std::ranges::sort - cppreference.com
https://en.cppreference.com/w/cpp/algorithm/ranges/sort