【问题标题】:Why do C++20 ranges not provide only pipe syntax?为什么 C++20 范围不只提供管道语法?
【发布时间】:2020-04-02 01:23:46
【问题描述】:

我知道这个问题听起来很奇怪,所以这里有一点上下文。

最近我很失望地得知 C++20 范围内的 map reduce 不能按预期工作,即

const double val = data | transform(...) | accumulate (...);

不行,你必须这样写不自然

const double val = accumulate(data | transform(...));

可以在herehere 找到详细信息,但归根结底是,accumulate 不能在 2 个不同的用例之间消除歧义。

这让我想到了:

如果 C++20 要求您必须使用管道来使用范围,也就是您可以编写

vector<int> v;
sort(v);

但你必须写

vector<int> v
v|sort();

这会解决歧义问题吗?

如果是这样,虽然对于使用 std::sort 和其他 STL 算法的人来说是不自然的,但我想知道从长远来看这是否是一个更好的设计选择。

注意: 如果这个问题太模糊,可以投票结束,但我觉得这是一个合理的设计问题,可以以相对公正的方式回答,特别是如果我对问题的理解是错误的。

【问题讨论】:

  • 不能消除哪两个不同的用例?如果你不解释,我们就无法理解你的底线问题。
  • @einpoklum-reinstateMonica 我提供了链接,我认为它太冗长而无法内联:stackoverflow.com/questions/59130785/…
  • 恕我直言,您可以用几句话来概括。 SO的习惯是不那么依赖链接的内容。无论如何,我明白你的意思;但我的回答是基于一般性的。

标签: c++ c++20 range-v3


【解决方案1】:

您需要区分范围算法和范围适配器。算法是对一系列值执行通用操作的函数。适配器是创建修改范围表示的范围视图的函数。适配器由| 操作符链接;算法只是常规函数。

有时,相同的概念性事物可以具有算法和适配器形式。 transform 既作为算法又作为适配器存在。前者将变换存储到输出范围中;后者创建输入的视图范围,根据请求延迟计算转换。

这些是针对不同需求和用途的不同任务。

另外,请注意 C++20 中没有 sort 适配器。排序适配器必须创建一个视图范围,该范围以某种方式混合在源范围中的元素周围。它必须为新的值序列分配存储空间(即使它只是将迭代器/指针/索引排序到值)。并且排序必须在构建时进行,因此不会发生惰性操作。

这也是accumulate 不能这样工作的原因。这不是“模棱两可”的问题;这是操作的基本性质的问题。累加从一个范围计算一个值;它不会根据现有范围计算新范围。这是算法的工作,而不是适配器。

有些任务在算法形式中很有用。有些任务以适配器形式很有用(你会发现很少有类似zip 的算法)。有些任务对两者都有用。但由于这是两个用于不同目的的独立概念,因此它们有不同的调用方式。

【讨论】:

  • OP 并没有声称你不能写那个。 OP 提出了一个你无法做到的假设设计。
  • @Barry:见我的最后一段。 这就是为什么这些是针对不同需求的不同任务。
  • 我不明白你在最后一段(过去是什么)中试图表达的观点。 range-v3 让我写 get_data() | actions::sort - 我看不到任何关于 | 的内容,如果我愿意,我将无法执行此类操作。
  • @Barry:现在你进入了一个完全独立的对话:actions,这是一个不同于适配器和算法的概念。
  • 他们根本不是分开的吗?我实际上并不认为这些东西中的任何一个都是有意义的不同——尤其是在语法方面。范围适配器是一种惰性算法,而动作是一种急切算法——适配器和动作在其中获取和产生范围。累积data | transform(f) | filter(g) | accumulate 无效的基本是什么?这是一件非常合理的事情,并且在其他语言/库中运行良好。
【解决方案2】:

这会解决歧义问题吗?

是的。

如果只有一种方式来写东西,那么这种方式一定是唯一可能的解释。如果算法“调用”只能是对算法的部分调用,必须通过左侧范围的| 操作完成,那么您甚至永远不会有算法调用是否为部分或全部。它总是片面的。

在这个意义上没有歧义。

但如果你走那条路,你最终会得到如下结果:

auto sum = accumulate("hello"s);

这实际上并没有对该字符串中的chars 求和,实际上是占位符,它正在等待一个范围与初始值"hello"s 累加。

【讨论】:

  • 怀着极大的悲伤,我接受了你的回答,我希望我误解了一些东西。 ://
猜你喜欢
  • 2021-04-14
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
  • 1970-01-01
  • 2014-11-01
相关资源
最近更新 更多