问题标签 [std-ranges]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
221 浏览

c++ - C++20 范围 - 如何将组合视图分配给变量?

有没有办法让它与 C++20 一起工作?

我收到了这个丑陋的错误:

test.cpp:13:10:错误:'operator=' 不匹配(操作数类型为 'std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >'和 'std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::operator|<std::ranges::views::<lambda(_Range&&) >::<lambda(_Up&& )> >') 13 | }); | ^ 在 test.cpp:2 中包含的文件中:/usr/include/c++/10/ranges:1155:14:注意:候选人:'constexpr std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges:: views::<lambda(_Range&&) >& std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >::operator=(const std::ranges::views ::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >& )' 1155 | 结构 _RangeAdaptorClosure : 公共 _RangeAdaptor<_Callable> | ^~~~~~~~~~~~~~~~~~~~ /usr/include/c++/10/ranges:1155:14: 注意:从'std::ranges: 参数1 没有已知的转换: :views::__adaptor::_RangeAdaptorClosurestd::ranges::views::__adaptor::operator|<std::ranges::views::<lambda(_Range&&) >::<lambda(_Up&&)> >' to 'const std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >&' /usr/include/c++/10/ranges:1155:14: 注意:候选:'constexpr std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::<lambda(_Range&&) >& std::ranges::views::__adaptor::_RangeAdaptorClosurestd::ranges::views::< lambda(_Range&&) >::operator=(std::ranges::views::__adaptor::_RangeAdaptorClosurestd::

我试着用谷歌搜索一些 RangeAdaptorClosure 的东西,但这没有多大意义

0 投票
2 回答
141 浏览

c++ - 为什么标准将borrowed_subrange_t 定义为common_range?

C++20 引入了ranges::borrowed_range,它定义了一个范围的要求,这样一个函数可以按值获取它并返回从它获得的迭代器,而不会有悬空的危险。简而言之(参考P2017R1):

当范围超出范围后您可以保留其迭代器时,范围就是一个借用范围。

同时,borrowed_subrange_t还引入了一个类型助手:

这是一个别名模板,由一些受约束的算法使用,例如ranges::uniqueranges::find_end避免返回潜在的悬空迭代器或视图。

当 type Rmodelsborrowed_range时,borrowed_subrange_tofR基本上是 a subrange<ranges::iterator_t<R>>,这意味着它也是 a ranges::common_range,因为它只接受一个模板参数,而第二个参数默认与第一个参数相同。

但是似乎有些误导,因为有些subrange类型可以借用但仍然不是common_range,请考虑以下代码:

subrange从 a 创建了两个 s borrowed_range ranges::iota_view,一个包含前 5 个元素,另一个包含itoa_view从第五个元素开始的所有元素。它们是subranges 的itoa_view,而且它们显然是借来的:

所以在某种程度上,它们的类型都可以看成是borrowed_subrange_t类型的itoa_view,但是根据定义,只有类型s1borrowed_subrange_t类型r,这也意味着下面的代码是非良构的,因为iota_view r它不是一个common_range

为什么标准需要保证borrowed_subrange_tof some range Ris a common_range,即begin()and的返回类型end()相同?这背后的原因是什么?为什么不更一般地定义它:

这样做会不会有任何潜在的缺陷和危险?

0 投票
3 回答
359 浏览

c++ - 可以使用 C++20 范围就地修剪字符串吗?

受 C++20 修剪的可爱 cppreference示例的启发,我编写了以下代码(我已将返回类型更改为void和 arg 为,std::string&因为我的“问题”(我正在发明学习 C++20 的问题)不存在于使用std::string_viewarg 并返回的原始代码std::string)。

这里的问题是这不是就地的,这意味着创建了新字符串。我可以编写更丑陋的代码来就地执行此操作,并且我知道传统的 C++ 算法不知道容器的存在,但我想知道 C++20 是否有一些技巧可以让我以优雅的方式进行修剪,但也是就地的。

这也是我丑陋的就地修剪(不确定它是否可以正常工作,但想法是它会就地修剪):

神螺栓

编辑:最初这个问题声称in.assign是 UB,但 TC 纠正了我。但根据我对 C++23 草案分配的理解,仍然会导致创建临时字符串。

0 投票
1 回答
249 浏览

c++ - C++20:如何按大小分割范围?

我想将范围拆分为 <任何大小{1, 2, 3, 4, 5}>的子范围范围(例如,大小为 2: )。然而仅按分隔符拆分。{{1, 2}, {3, 4}, {5}}std::views::split

是否没有标准的“反向连接”或这样做的东西?

0 投票
2 回答
149 浏览

c++ - range-v3 中的 view_closure 是什么?

在这样的情况下:

closure似乎是一个view_closure。我确实明白最后一行没有多大意义,因为变换没有应用到任何地方。实际上,我也可以将一个向量x导入closure,它既可以编译又可以正常工作

但是,什么视图关闭?它是一个期望在某处应用的“类似函数”的对象吗?它的语义是什么?

我从 Eric Niebler 的源代码中找到了这一点range-v3,但没有任何文档在其他地方指定它。

我什至不知道view_closure是供内部使用还是供用户使用。

0 投票
2 回答
219 浏览

c++ - 为什么 Ranges 库中的 std::views::take_while 需要 const 谓词?

TL;DR:我正在使用Ranges库中的范围和相应的范围适配器。范围适配器和谓词都从输入序列中排除某些元素。为什么带谓词而不带谓词?std::views::take_whilestd::views::filtertake_whileconstfilter

背景故事

我有一个std::vector<int>并且想要迭代它,但是我想在点击一个时停止迭代5。通过使用范围适配器std::views::take_while,我可以实现如下:

输出:

值:8
值:2

但是,我现在也想处理5,因此循环必须进一步运行一个迭代步骤。我没有找到合适的范围适配器,所以我编写了以下有状态的 lambda 表达式:

此 lambda 表达式会记住何时i != 5违反条件并false在下一次调用时返回。然后我将它传递给std::views::take_while如下:

但是,对于上面的代码,编译器会抛出一个很长的错误消息。由于无法发现问题,我仔细检查了 of 的声明,std::views::take_while发现谓词Pred必须是const. 寻找替代方案,我检查了std::views::filter. 有趣的Pred是,不需要const这里。所以我将上面的可变 lambda 传递给范围适配器std::views::filter,如下所示:

此代码编译并提供所需的输出:

值:8
值:2
值:5

魔杖盒上的代码

这引出了我的问题:为什么谓词std::views::take_while有,而没有?conststd::views::filter

0 投票
1 回答
130 浏览

c++ - range::views 如何实现 O(1) 复杂度?

在最近介绍的 C++20 Ranges 中,我知道views通过使用视图适配器来实现可组合性。我也知道视图不拥有它们的元素并且它们的本质是惰性的,也就是说它们只在需要时才进行实际计算。

视图如何实现O(1)移动、复制和分配操作的复杂性?对我来说可能的答案是,视图只是“待计算”操作的描述,它们只是指数据及其转换。

不过,这听起来像是视图只是承担了表达我们编码序列的工作,并且只有在传递给一些急切的事物(例如算法)时,它们才会在这个特定的单个调用中显示所有计算负载。

后续问题:我可以理解如何实现O(1)复制,本质上是指可复制对象(尽管我不知道这是否是什么ranges::views)。但我无法理解这将如何在分配操作中发挥作用。同样,一个可能的答案是,因为所有这些都发生在编译时,所以再次只是“描述”分配是一个O(1)操作。但是改变std::vector<int>视图所看到的,是一个运行时操作(很好的例子)。这还是O(1)手术吗?

0 投票
2 回答
277 浏览

c++ - 为什么`iota(0) | take(0)` 不是 C++20 中的模型范围::sized_range?

考虑以下代码片段:

gcc-trunk拒绝它,因为required-expression std::ranges::size(r)无效。为什么r没有 model ranges::sized_range,即为什么我不能使用std::ranges::size它?

更新

使用range-v3后编译。C++23 是否需要此功能,还是 LWG 问题?

问题似乎是sentinel_tinr恰好range-v3满足ranges::default_sentinel,因为这两种类型在[predef.iterators#iterators.counted]std::sized_sentinel_for<ranges::counted_iterator>中有一个有效的:operator-

但是在 中namepace std::rangessentinel_tofrstd::ranges::take_view<std::ranges::iota_view>::_Sentinel<true>不能转换成的std::default_sentinel_t

0 投票
1 回答
372 浏览

c++ - 使用范围初始化向量与 lambda 内联初始化

我想通过转换另一个向量来初始化一个向量。我用两种内联初始化的方式进行了测试std::vector

一种使用 lambda 内联初始化(带std::transform):

而另一个 - 使用std::ranges::views::transform

我预计两种向量初始化方式都应该具有相似的性能,但由于某种原因,传统解决方案的基准std::transform比第二种方法快得多(快 9.7 倍 -> https://quick-bench.com/q/3PSDRO9UbMNunUpdWGNShF49WlQ) .

我的问题是:

  • 我使用std::ranges::views::transform不正确吗?
  • 为什么它工作得这么慢?

旁注 - 可以使用 来完成boost::make_transform_iterator,但我无法在快速台上检查它,因为它们不支持 boost。所以我不确定这种解决方案的效率。

0 投票
1 回答
131 浏览

c++ - 如何打印范围?

我正在尝试使用范围比较 2 个数组并想打印它。

但未能编译错误我不明白

有没有办法打印 found1 ?