问题标签 [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.
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 的东西,但这没有多大意义
c++ - 为什么标准将borrowed_subrange_t 定义为common_range?
C++20 引入了ranges::borrowed_range,它定义了一个范围的要求,这样一个函数可以按值获取它并返回从它获得的迭代器,而不会有悬空的危险。简而言之(参考P2017R1):
当范围超出范围后您可以保留其迭代器时,范围就是一个借用范围。
同时,borrowed_subrange_t还引入了一个类型助手:
这是一个别名模板,由一些受约束的算法使用,例如ranges::unique和ranges::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,但是根据定义,只有类型s1是borrowed_subrange_t类型r,这也意味着下面的代码是非良构的,因为iota_view r它不是一个common_range:
为什么标准需要保证borrowed_subrange_tof some range Ris a common_range,即begin()and的返回类型end()相同?这背后的原因是什么?为什么不更一般地定义它:
这样做会不会有任何潜在的缺陷和危险?
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 草案分配的理解,仍然会导致创建临时字符串。
c++ - C++20:如何按大小分割范围?
我想将范围拆分为 <任何大小{1, 2, 3, 4, 5}>的子范围范围(例如,大小为 2: )。然而仅按分隔符拆分。{{1, 2}, {3, 4}, {5}}std::views::split
是否没有标准的“反向连接”或这样做的东西?
c++ - range-v3 中的 view_closure 是什么?
在这样的情况下:
closure似乎是一个view_closure。我确实明白最后一行没有多大意义,因为变换没有应用到任何地方。实际上,我也可以将一个向量x导入closure,它既可以编译又可以正常工作。
但是,什么是视图关闭?它是一个期望在某处应用的“类似函数”的对象吗?它的语义是什么?
我从 Eric Niebler 的源代码中找到了这一点range-v3,但没有任何文档在其他地方指定它。
我什至不知道view_closure是供内部使用还是供用户使用。
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
c++ - range::views 如何实现 O(1) 复杂度?
在最近介绍的 C++20 Ranges 中,我知道views通过使用视图适配器来实现可组合性。我也知道视图不拥有它们的元素并且它们的本质是惰性的,也就是说它们只在需要时才进行实际计算。
视图如何实现O(1)移动、复制和分配操作的复杂性?对我来说可能的答案是,视图只是对“待计算”操作的描述,它们只是指数据及其转换。
不过,这听起来像是视图只是承担了表达我们编码序列的工作,并且只有在传递给一些急切的事物(例如算法)时,它们才会在这个特定的单个调用中显示所有计算负载。
后续问题:我可以理解如何实现O(1)复制,本质上是指可复制对象(尽管我不知道这是否是什么ranges::views)。但我无法理解这将如何在分配操作中发挥作用。同样,一个可能的答案是,因为所有这些都发生在编译时,所以再次只是“描述”分配是一个O(1)操作。但是改变std::vector<int>视图所看到的,是一个运行时操作(很好的例子)。这还是O(1)手术吗?
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::ranges,sentinel_tofr是std::ranges::take_view<std::ranges::iota_view>::_Sentinel<true>不能转换成的std::default_sentinel_t。
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。所以我不确定这种解决方案的效率。
c++ - 如何打印范围?
我正在尝试使用范围比较 2 个数组并想打印它。
但未能编译错误我不明白
有没有办法打印 found1 ?