C++ C++;20个范围太多|运算符?

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 ==

我使用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 == 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
    be
    std::reverse\u迭代器
result3
的初始值设定项中:

  • ..的迭代器类型取(4)
    is
    std::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)