通过索引访问 range-v3 视图元素的便捷方法

问题描述 投票:0回答:1

我正在寻找一种方法来访问,例如,按索引过滤的视图元素。这是上下文的代码片段:

std::vector<int> v = {1, 2, 3, 4, 5};
auto v_view = v | ranges::views::filter([](int value) { return value & 1; });

现在我想访问第二个元素:

v_view.at(1) /* do some stuff */;

这不会编译并显示以下日志:

error: no matching member function for call to 'at'
   20 |     if (v_view.at(3) == 3) {
      |         ~~~~~~~^~
/opt/compiler-explorer/libs/rangesv3/0.12.0/include/range/v3/view/interface.hpp:309:46: note: candidate template ignored: constraints not satisfied [with True = true]
  309 |         constexpr range_reference_t<D<True>> at(range_difference_t<D<True>> n)
      |                                              ^
/opt/compiler-explorer/libs/rangesv3/0.12.0/include/range/v3/view/interface.hpp:308:31: note: because 'D<true>' (aka 'ranges::remove_if_view<ranges::ref_view<std::vector<int>>, ranges::logical_negate<(lambda at <source>:18:45)>>') does not satisfy 'random_access_range'
  308 |             requires True AND random_access_range<D<True>> AND sized_range<D<True>>)

看起来该函数应该具有恒定的时间复杂度,并且仅适用于随机访问范围,但事实显然并非如此。不过,我不清楚为什么不允许对具有线性复杂度的非连续范围进行重载。我看到的唯一解决方法是:

*ranges::next(v_view.begin(), 1) /* do some stuff */;

可能我错过了一些东西。是否有任何选项可以使用索引来处理视图,或者我是否被迫显式处理其迭代器?

c++ iterator random-access range-v3
1个回答
1
投票

不过,我不清楚为什么不允许对具有线性复杂度的非连续范围进行重载。

核心准则之一是“不要浪费时间或空间”。.

此处缺少

at
与 std 容器相匹配。
std::list
仅是双向的,因为访问任意元素的最著名方式是线性的,它不提供
at
operator[]
std::forward_list
仅是向前的,因为获取前一个元素的最佳已知方法是线性1,它不提供反向迭代器。

如果您编写一个函数模板,采用任意容器并对其进行索引,您可以知道该函数针对每个标准容器的专业化的时间复杂度,因为索引要么是恒定时间,要么不存在。在某些情况下,你没有一个“默默地更糟糕”的算法。 如果你不关心复杂性,你可以写一个自由函数

at

template <std::ranges::forward_range Range>
std::ranges::range_reference_t<Range> at(Range & range, std::ranges::range_difference_t<Range> index) {
    return *std::ranges::next(range.begin(), index);
}

或者,如果您要通过索引进行多次访问,您可以具体化过滤视图

std::vector<int> v = {1, 2, 3, 4, 5}; auto v_filtered = v | std::ranges::views::filter([](int value) { return value & 1; }) | std::ranges::to<std::vector<int>>;

数一下距离
    begin
  1. 有多远,然后少前进
    begin
    一次
    
        
© www.soinside.com 2019 - 2024. All rights reserved.