为什么 C++20 范围不只提供管道语法?
Why do C++20 ranges not provide only pipe syntax?
我知道这个问题听起来很奇怪,所以这里有一些背景。
最近我很失望地得知 C++20 范围内的地图缩减并不像人们预期的那样工作,即
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
初始值。
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- IPC使用多个管道和分支进程来运行Python程序
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 如何创建函数管道,以便函数一个接一个地运行?
- 单独定义模板化嵌套类方法的正确语法
- Gstreamer 管道从命令 lne 到 c 代码
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 外壳包装器句柄/执行交互式命令管道C++ UNIX
- 为什么我会收到错误 C2143 语法错误:缺少"*"之前的';'?
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 将旧管道转换为现代 openGL 时出现问题
- 为什么 C++20 范围不只提供管道语法?
- Gstreamer管道语法