我可以通过管道传输到 range-v3 accumulate 吗?

Can I pipe to range-v3 accumulate?

我发现 3 年前的旧问题说一般来说这是不可能的,但我真的很想积累,因为在某些情况下它非常好,例如这个:

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

所以我想知道是否已将某些东西添加到 range-v3/C++20 范围,使我能够做到这一点。

没有

您唯一可以输入的是范围适配器——接受范围并产生范围的算法。采用范围和 return 单个对象(也称为变形)的算法在范围 v3 或 C++20 范围内 不可 管道化。

你必须这样写:

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

至于为什么 accumulate 和类似的算法将努力成为 |-able。考虑一下我们希望 algo(rng, x)rng | algo(x) 表示相同的意思。此外,考虑 "total call" algo(rng, x) 可以完全约束(因为您拥有所有信息),而 "partial call" algo(x) 基本上必须在所有情况下完全不受约束,但在极少数情况下...基本上大致取 auto&&...

问题是当第二个参数 x 可以 是一个范围时,我们必然 运行 陷入歧义。您如何区分意图是完全调用还是部分调用?

这是一个使用 string 的例子:

accumulate("hello"s, ""s)

这是一个总调用,它使用默认的二元运算符 + - 这是字符串连接。它所做的是遍历 chars 范围内的元素,并将它们一个一个地添加到初始空字符串中。这是复制 string 的一种低效但正确的方法。您最终得到的值是 "hello"s.

它的等效管道版本呢?

"hello"s | accumulate(""s)

右边是什么意思? accumulate(""s) 可以算作总调用吗?是的,它可以!默认的第二个参数是 char(),默认的第三个参数是 plus(),这很好用,所以 accumulate(""s) 的值是整数 0 - 使得整个表达式格式错误,因为没有 operator|(string, int)

如何使用 accumulate 来完成这项工作?