C++ C++;20个范围太多|运算符?
我使用g++10.2编写这段代码。有人知道为什么我在C++ C++;20个范围太多|运算符?,c++,compiler-errors,c++20,std-ranges,C++,Compiler Errors,C++20,Std Ranges,我使用g++10.2编写这段代码。有人知道为什么我在results3上的最后一个std::views::reverse出现编译器错误吗 #include <vector> #include <ranges> int main() { auto values = std::vector{1,2,3,4,5,6,7,8,9,10}; auto even = [](const auto value) { return value % 2 ==
results3
上的最后一个std::views::reverse
出现编译器错误吗
#include <vector>
#include <ranges>
int main() {
auto values = std::vector{1,2,3,4,5,6,7,8,9,10};
auto even = [](const auto value) {
return value % 2 == 0;
};
auto square = [](const auto value) {
return value * value;
};
auto results1 = values
| std::views::filter(even)
| std::views::reverse
| std::views::take(4)
| std::views::reverse;
auto results2 = values
| std::views::transform(square)
| std::views::reverse
| std::views::take(4)
| std::views::reverse;
auto results3 = values
| std::views::filter(even)
| std::views::transform(square)
| std::views::reverse
| std::views::take(4)
| std::views::reverse; // Error happens on this line.
}
#包括
#包括
int main(){
自动值=标准::向量{1,2,3,4,5,6,7,8,9,10};
自动偶数=[](常量自动值){
返回值%2==0;
};
自动平方=[](常数自动值){
返回值*值;
};
自动结果1=值
|标准::视图::过滤器(偶数)
|std::views::reverse
|std::views::take(4)
|std::views::reverse;
自动结果2=值
|标准::视图::变换(方形)
|std::views::reverse
|std::views::take(4)
|std::views::reverse;
自动结果3=值
|标准::视图::过滤器(偶数)
|标准::视图::变换(方形)
|std::views::reverse
|std::views::take(4)
|std::views::reverse;//此行发生错误。
}
错误代码段:
。。。
:在函数“int main()”中:
:30:9:错误:与“运算符|”不匹配(操作数类型为“std::ranges::take_view”和“const std::ranges::views::u适配器::_rangeAdapterClosure”)
25 |自动结果3=值
| ~~~~~~
26 | |标准::视图::过滤器(偶数)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
27 | |标准::视图::变换(方形)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 | |标准::视图::反向
| ~~~~~~~~~~~~~~~~~~~~~
29 | | std::views::take(4)
| ~~~~~~~~~~~~~~~~~~~~~
| |
|标准::范围::查看
30 | |标准::视图::反向;
| ^ ~~~~~~~~~~~~~~~~~~~
| |
|常量标准::范围::视图::u适配器::RangeAdapterClosure
...
这里可以看到完整的错误集:EDITMSVC似乎表现出相同的行为,因此我的答案中的结论可能不正确 我认为这是
take\u view
实现中的一个bug
引用查看
页面上的内容(重点是我的):
take_view对连续范围、随机访问范围、,
双向\u范围、前进\u范围、输入\u范围和大小\u范围
基础视图V为各自的概念建模
考虑到以下代码,我们看到进位范围的输入是一个双向\u范围
:
auto input_to_take = values
| std::views::filter(even)
| std::views::transform(square)
| std::views::reverse;
static_assert(std::ranges::bidirectional_range<decltype(input_to_take)>); // No error here.
我认为这与参考文献中的内容相矛盾
既然take视图不是双向视图,那么示例中的以下反向视图无法编译,因为它需要一个双向范围作为输入
活生生的例子。TL;DR:在这种情况下,std::views::take
的结果的迭代器类型是std::counted\u iterator
,当迭代器概念预计不会失败时,它有时会失败。这是,并已由解决
这涉及到一些非常复杂的机制
让
T
是值的迭代器类型| std::views::filter(偶数)| std::views::transform(square)
R
bestd::reverse\u迭代器
在result3
的初始值设定项中:
..的迭代器类型取(4)
isstd::counted\u迭代器
std::counted\u迭代器
的iterator\u traits
与部分专门化std::iterator\u traits
匹配
所述部分专门化源自std::iterator\u traits
std::iterator_traits
是从主模板生成的:它提供名为iterator_category
的成员,但不提供名为iterator_concept
的成员
R
的iterator\u类别与T
的类别相同
T
的iterator\u类别
是input\u iterator\u标记
,因为其解引用运算符不返回引用,这是C++17 ForwardIterator要求所不允许的。(T
的迭代器概念是双向迭代器标签
)
所以最后,std::iterator\u traits
没有提供iterator\u概念
,它的iterator\u类别
是input\u iterator\u标记
因此,的结果take(4)
无法建模双向\u范围
,因此它被视图::reverse拒绝
(迭代器类型为。| take(4)当从管道中删除过滤器时,
不是计数的迭代器
;当从管道中删除变换
时,迭代器类别
不是输入迭代器标签
。因此结果1
和结果2
不会触发此错误。)
这本质上是。有趣的注意:如果将变换向下移动,超过最后一个反向
,它将成功编译。我想知道范围适配器的确切顺序是否与CTAD或概念约束要求相冲突。我很想知道这是否是标准/正确的行为,或者这是否是一个实现问题如果是这样的话,前两个示例是否也无法编译,因为它们都在使用反转之前使用take
?是的,所以我认为这是实现中的一个bug。在某些情况下,输入范围的双向性会丢失,而在另一些情况下则不会。。。。这将是固定的,这是现代C++ + HUH?@ QWR,如果你仍然能理解它是如何工作的,它还不够现代:)杰里米弗里斯纳,我没有。我原以为我理解迭代器,但现在它们被弃用了?P2259被选为C++23。草本植物
auto t = take_view(input_to_take, 4);
static_assert(std::ranges::bidirectional_range<decltype(t)>); // Error (constraints not satisfied)