问题标签 [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 R
modelsborrowed_range
时,borrowed_subrange_t
ofR
基本上是 a subrange<ranges::iterator_t<R>>
,这意味着它也是 a ranges::common_range
,因为它只接受一个模板参数,而第二个参数默认与第一个参数相同。
但是似乎有些误导,因为有些subrange
类型可以借用但仍然不是common_range
,请考虑以下代码:
我subrange
从 a 创建了两个 s borrowed_range
ranges::iota_view
,一个包含前 5 个元素,另一个包含itoa_view
从第五个元素开始的所有元素。它们是subrange
s 的itoa_view
,而且它们显然是借来的:
所以在某种程度上,它们的类型都可以看成是borrowed_subrange_t
类型的itoa_view
,但是根据定义,只有类型s1
是borrowed_subrange_t
类型r
,这也意味着下面的代码是非良构的,因为iota_view
r
它不是一个common_range
:
为什么标准需要保证borrowed_subrange_t
of some range
R
is a common_range
,即begin()
and的返回类型end()
相同?这背后的原因是什么?为什么不更一般地定义它:
这样做会不会有任何潜在的缺陷和危险?
c++ - 可以使用 C++20 范围就地修剪字符串吗?
受 C++20 修剪的可爱 cppreference示例的启发,我编写了以下代码(我已将返回类型更改为void
和 arg 为,std::string&
因为我的“问题”(我正在发明学习 C++20 的问题)不存在于使用std::string_view
arg 并返回的原始代码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_while
std::views::filter
take_while
const
filter
背景故事
我有一个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
有,而没有?const
std::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_t
inr
恰好range-v3
满足ranges::default_sentinel
,因为这两种类型在[predef.iterators#iterators.counted]std::sized_sentinel_for<ranges::counted_iterator>
中有一个有效的:operator-
但是在 中namepace std::ranges
,sentinel_t
ofr
是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 ?