c++ - 在什么情况下 ref_view{E} 格式错误而 subrange{E} 不是?

标签 c++ c++20 range-v3 std-ranges

C++20 介绍 views::all 这是一个范围适配器,返回 view这包括其范围参数的所有元素。
表达式 views::all(E)是表达式等效(具有相同的效果)到:

  • decay-copy(E)如果E的衰变类型型号 view .
  • 否则,ref_view{E}如果该表达式格式正确
  • 否则,subrange{E}

  • 第一种情况代表一个 view 的类型在使用 views::all 管道传输后不会改变( goldbot ):
    auto r = views::iota(0);
    static_assert(std::same_as<decltype(r), decltype(r | views::all)>);
    
    第二种情况用于包装一个 viewable_range ref_view为方便范围管道操作:
    int r[] = {0, 1, 2};
    static_assert(std::same_as<ranges::ref_view<int[3]>, decltype(r | views::all)>);
    
    但是关于第三种情况,我想不出是在什么情况下subrange{E}格式良好且ref_view{E}是畸形的。
    它的目的是什么?有人可以举一个例子吗?

    最佳答案

    But regarding the third case, I can't think of under what circumstances subrange{E} is well-formed and ref_view{E} is ill-formed.

    ref_view{E}仅适用于左值范围。subrange{E}仅适用于借用范围。您可以在 [range.subrange.general] 中找到其扣除指南。 :
    template<borrowed_­range R>
      subrange(R&&) ->
        subrange<iterator_t<R>, sentinel_t<R>,
                 (sized_­range<R> || sized_­sentinel_­for<sentinel_t<R>, iterator_t<R>>)
                   ? subrange_kind::sized : subrange_kind::unsized>;
    
    借用范围再次是左值或选择从中借用的范围。类型如 string_viewspan例如,是借来的。
    所以如果你有类似右值的东西 vector<int> ,那么这不是 View (第一项),也不能构建 ref_view从它(因为它是一个右值),你也不能构造一个 subrange从它(因为它是一个非借用的范围)。

    我意识到这并不能完全回答问题,因为我在输入答案时颠倒了头脑中的极性。但是T.C.'s got me covered .
    另一个纯粹假设的例子是一个非 View 范围,它将其内容存储在 shared_ptr 中。 ,然后它的迭代器也共享该数据。就像是:
    struct SharedVector {
        std::shared_ptr<std::vector<int>> data;
    
        struct Iterator {
            std::shared_ptr<std::vector<int>> data;
            std::vector<int>::iterator cur;
    
            // ...
        };
    
        auto begin() -> Iterator { return {data, data->begin()}; }
        auto end() -> Iterator { return {data, data->end()}; }
    };
    
    右值 SharedVector不会是一个 View (不是 O(1) -可破坏的),你不能 ref_view{E}它(因为它是一个右值),但这样的范围仍然可以借用,所以 subrange{E}可以工作。

    关于c++ - 在什么情况下 ref_view{E} 格式错误而 subrange{E} 不是?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67466714/

    相关文章:

    c++ - 将 n 个 vector 组合成一个 n 元组 vector

    对 Range-v3 压缩容器进行排序 - 我可以解压吗?

    c++ - 无法在 qSqlite ( QT 5.9) 中加载 Spatialite 扩展

    c++ - 仅计算强度降低的边缘

    c++ - 概念可能会取代 C++ 中的类型特征吗?

    c++ - 何时在 constexpr 函数中使用模板非类型类或普通参数

    c++ - range-v3 如何操作::使用定界符加入

    c++ - 虚拟方法错误 (0x0) 地址

    具有类键和类值的 C++ STL 映射容器

    c++ - 在 C++20 中,计算范围内相邻对的最简洁明了的方法是什么?