3

C++20 引入了views::allwhich 是一个范围适配器,它返回view包含其范围参数的所有元素的 a。

该表达式views::all(E)与以下表达式等效(具有相同的效果):

  • decay-copy(E)如果是腐烂类型的E模型view
  • 否则,ref_view{E}如果该表达式是格式良好的
  • 否则,subrange{E}

第一种情况表示 a的类型在使用(goldbotview )管道后没有改变:views::all

auto r = views::iota(0);
static_assert(std::same_as<decltype(r), decltype(r | views::all)>);

第二种情况用于包装viewable_rangewithref_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}良构。

它的目的是什么?有人可以举个例子吗?

4

3 回答 3

4

但是关于第三种情况,我想不出在什么情况下subrange{E}是良构和ref_view{E}良构。

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_view和之类的类型span是借用的。

因此,如果您有类似 rvalue 的东西vector<int>,那么这不是视图(第一个项目符号),也不能从中构造 a ref_view(因为它是右值),也不能从中构造 a subrange(因为它是非借用范围)。


我意识到这并不能完全回答问题,因为我在输入答案时翻转了脑海中的极性。但是TC 让我满意

另一个纯粹假设的例子是一个非视图范围,它将其内容存储在 ashared_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不是视图(不可O(1)破坏),你不能ref_view{E}(因为它是右值),但这样的范围仍然可以借用,所以subrange{E}可以工作。

于 2021-05-10T13:07:50.550 回答
4

借用的右值非视图范围(视图将属于第一个项目符号,因此不会出现问题)。

当前标准中的典型示例是span非零静态范围(如span<int, 42>)。另一个示例是不支持赋值的假设借用范围类型。也可以构建综合示例(因为两者borrowed_range都是view可选的)。

于 2021-05-10T13:27:15.570 回答
2
template<__NotSameAs<ref_view> T>
requires std::convertible_to<T, R&> && requires { _FUN(std::declval<T>()); }
constexpr ref_view(T&& t);

由此看来,右值似乎有问题。

template<class R>
ref_view(R&) -> ref_view<R>;

看起来它也阻止了右值。

做一个你可以的右值subrange{E}。就像一个子范围右值。可能是其他人,取决于子范围的扣除指南。

于 2021-05-10T10:23:36.233 回答