繁体   English   中英

为什么 C++20 范围不只提供管道语法?

[英]Why do C++20 ranges not provide only pipe syntax?

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

最近我很失望地得知 C++20 范围内的 map reduce 并没有像人们期望的那样工作,即

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

不起作用,您必须以这种不自然的方式编写它:

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

可以在此处此处找到详细信息,但归结为累积无法消除 2 个不同用例之间的歧义的事实。

所以这让我想到:

如果 C++20 要求你必须使用管道来使用范围,也就是你不能

vector<int> v;
sort(v);

但你必须写

vector<int> v
v|sort();

那会解决歧义问题吗?

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

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

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

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

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

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

这也是为什么accumulate不能那样工作的原因。 这不是“歧义”的问题; 这是操作的基本性质的问题。 累加从一个范围计算一个值; 它不会从现有范围计算新范围。 那是算法的工作,而不是适配器的工作。

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

那会解决歧义问题吗?

是的。

如果只有一种写东西的方式,那一种方式一定是唯一可能的解释。 如果算法“调用”只能是对算法的部分调用,必须用|完成| 在左侧有一个范围的操作,那么你甚至永远不会有算法调用是部分还是全部的问题。 它总是片面的。

在这个意义上没有歧义。

但是如果你走那条路,你最终会得到这样的结果:

auto sum = accumulate("hello"s);

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM