【发布时间】:2020-03-26 14:03:31
【问题描述】:
我发现 3 年前的旧问题说一般来说这是不可能的,但我真的很想通过管道累积,因为在某些情况下它非常好,例如:
const double val = data | transform(...) | accumulate (...);
所以我想知道是否已将某些内容添加到 range-v3/C++20 范围以使我能够执行此操作。
【问题讨论】:
我发现 3 年前的旧问题说一般来说这是不可能的,但我真的很想通过管道累积,因为在某些情况下它非常好,例如:
const double val = data | transform(...) | accumulate (...);
所以我想知道是否已将某些内容添加到 range-v3/C++20 范围以使我能够执行此操作。
【问题讨论】:
没有。
您可以输入的唯一内容是范围适配器 - 接受范围并产生范围的算法。接受一个范围并返回单个对象(也称为 catamorphisms)的算法在 range-v3 或 C++20 范围内是不可管道化的。
你必须这样写:
const double val = accumulate(data | transform(...));
至于为什么accumulate 和类似的算法很难成为|-able。考虑一下我们希望algo(rng, x) 和rng | algo(x) 具有相同的含义。此外,考虑到“总调用”algo(rng, x) 可以完全受限(因为您拥有所有信息),而“部分调用”algo(x) 基本上必须在除极少数情况外的所有情况下完全不受约束......基本上大致采用auto&&...
问题是当第二个参数x也可以是一个范围时,我们必然会遇到歧义。您如何区分意图是完全调用还是部分调用?
这是一个使用 string 的示例:
accumulate("hello"s, ""s)
这是一个总调用,它使用默认的二元运算符+ - 这是字符串连接。这样做是遍历chars 范围内的元素,并将它们一一添加到初始空字符串中。这是复制string 的低效但正确的方法。您最终会得到值"hello"s。
它的等效管道版本呢?
"hello"s | accumulate(""s)
右边是什么意思? accumulate(""s) 可以被视为总通话吗?是的,它可以!默认的第二个参数是char(),默认的第三个参数是plus(),这很好用,所以accumulate(""s)的值是整数0——使得整个表达式格式不正确,因为没有@ 987654342@。
您如何使用accumulate 完成这项工作?
【讨论】:
accumulate 成为管道。