gpt4 book ai didi

c++ - 为什么 views::reverse 可以将 non-sized_range 转换为 size_range?

转载 作者:行者123 更新时间:2023-12-04 11:50:16 34 4
gpt4 key购买 nike

[range.sized#1] :

The sized_­range concept refines range with the requirement that thenumber of elements in the range can be determined in amortizedconstant time using ranges​::​size.

template<class T>   
concept sized_­range =
range<T> &&
requires(T& t) { ranges::size(t); };

标准规定,获取 ranges::sized_range 的大小 保证在恒定时间内 .考虑以下:
auto r1 = std::views::iota(0)
| std::views::filter([](int x){ return x % 2 == 0; })
| std::views::take(1'000'000);
r1显然不是 sized_range ,因为不可能得到它的大小
恒定时间,这也意味着我们使用 ranges::size评估其大小也是格式错误的。
但是我偶然发现如果我们申请 views::reverse 在它上面,新的范围 r2突然变成 sized_range ,我们可以直接使用 ranges::size正确获取其大小, godbolt :
auto r2 = r1 | views::reverse;

static_assert(!ranges::sized_range<decltype(r1)>);
static_assert( ranges::sized_range<decltype(r2)>);
std::cout << std::ranges::size(r2) << "\n"; // print 500'000
但是,很明显,新范围 r2不是 sized_range ,因为我们永远无法在恒定时间内获得它的大小,这似乎违反了标准所说的。
为什么可以 views::reverse转换非 sized_rangesized_range ?显然,这种转换不会对原始范围的大小产生任何影响。这是标准缺陷还是库错误?

最佳答案

要求是摊销常数,并不总是常数。

  • take_view<...>生产 counted_iterator s。
  • 所以reverse_view<take_view<...>>生产 reverse_iterator<counted_iterator<...>>
  • counted_iterator s 总是可以减去:您只需减去计数。
  • 所以reverse_iterator<counted_iterator<...>>也总是可以减去。
  • ranges::size为迭代器/哨兵模型 sized_sentinel_for 的任何范围定义.这包括 reverse_view<take_view<...>> .

  • 为满足摊销常数复杂性要求, reverse_view::begin如果需要计算它,则缓存源范围的末尾(即,源范围不常见)。

    关于c++ - 为什么 views::reverse 可以将 non-sized_range 转换为 size_range?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67194689/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com