问题标签 [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++ - Range-v3 视图组合和视图计算并行化
取自 range-v3 文档,以下示例演示了一个简单的views
流水线组合以生成range
:
我知道这views::foo
相当于类似的东西foo_view()
,因此上面的示例最终如下:
现在的问题是:
remove_if
和操作的顺序是如何transform
发生的?(我知道他们是懒惰的,他们实际上并没有在这一步计算,而不是稍后rng
具体化,但这不是重点)。
我可以在这里看到两个选项:
这些操作由 range-v3融合
rng
,当通过某个迭代器访问给定的元素时,这两个操作因此应用于该元素。当请求给定元素时,整个
remove_if
操作将被应用vi
,然后该操作的输出向量被馈送到transform
. 因此,我们最终得到了一个完整的“ trasformed + removed_if ”向量,它使我们能够访问所需的元素。
我很确定选项(1)是实际发生的事情。如果是这样的话,range-v3 是如何做到这一点的呢?它是否具有某种通用组合代码以组合无限数量的按视图组合操作?
附带问题:range-v3 视图公开了什么样的迭代器?我认为random-access
迭代器下方的任何内容都会使并行化变得不可能。
range-algorithms
元问题:如果选项(1)是事实,那么考虑到它们将一个简单的范围(由多个视图组成,通过操作融合按需计算)作为输入,并行化不是非常简单吗?
c++ - 为什么 views::reverse 可以将 non-sized_range 转换为 size_range?
该
sized_range
概念对范围进行了细化,要求范围内的元素数量可以在摊销的 常数时间内使用来确定ranges::size
。
该标准规定,保证在恒定时间内获得 的大小。考虑以下:ranges::sized_range
r1
显然不是sized_range
,因为不可能在常数时间内得到它的大小,这也意味着我们ranges::size
用来评估它的大小也是病态的。
但我偶然发现,如果我们应用views::reverse
它,新的范围r2
突然变成了 a sized_range
,我们可以直接使用godboltranges::size
来正确获取它的大小:
但是,很明显新范围r2
不是 a sized_range
,因为我们永远无法在恒定时间内得到它的大小,这似乎违反了标准所说的。
为什么可以views::reverse
将非sized_range
变成a sized_range
?显然,这种转换不会对原始范围的大小产生任何影响。这是标准缺陷还是库错误?
c++ - 范围的 std::lexicographical_compare_three_way
为什么有std::lexicographical_compare_three_way
,但没有std::ranges::lexicographical_compare_three_way
?
有参数 Comp std::ranges::lexicographical_compare
,但它相当没用,因为函数返回bool
,当需要比较类别类型之一时。
以下是 cppref 的一些链接
https://en.cppreference.com/w/cpp/algorithm/lexicographical_compare_three_way
https://en.cppreference.com/w/cpp/algorithm/ranges/lexicographical_compare
c++ - C++20 views::join 在生成的嵌套范围内进入无限循环::single_view
我正在使用具有 GCC 实现(v10.2 和 v11)的 C++20 范围。
为了测试 的行为std::views::join
,我尝试使用生成嵌套视图,single
然后使用.join
我希望找到一个具有初始值 (1)的for循环迭代器。但是没有......它进入了一个无限循环,因为我使用了这个值,所以它会出现段错误。
std::views::single
如果我用std::views::iota(a,b)
or替换嵌套std::views::empty<int>
,则行为完全可以。
您知道这是否是正确的预期行为(以及为什么)?
编辑
std::ranges::next(v.begin()) == v.end()
一定是真的。
这是 GCC 10.3 和 11.1 中的一个错误。
它已在 GCC 主干和 11.1.1 中修复。
c++ - 在 C++20 中引入的 std::views::all 是什么?
成功编译g++11 -std=c++20
。但我无法区分v | std::views::drop(2)
和之间的任何区别std::views::all(v) | std::views::drop(2)
。
所以,我的问题是:
C++20 中引入了什么?std::views::all
c++ - 如何在自定义容器中支持范围适配器?
我创建了一个名为goldbox
仅包含算术类型的自定义容器,并且我还实现begin
了end
成员函数来迭代元素。
我的完整源代码:
输出:
但我想使用范围来使用它,这样我就不必创建新实例。
一旦我应用了goldbox
基于范围的 for 循环内部:
它会引发错误,因为我没有提供operator|
.
如果我使用非管道语法:
它仍然会抛出一个错误,两者begin
都end
没有在范围内声明。
c++ - 为什么`std::ranges::clamp`如此严格地限制投影的数量?
根据[alg.clamp#5],时间复杂度std::ranges::clamp
最多需要 2 次比较和3次投影应用。cppreference中的可能实现由下式给出:
这显然不符合要求,因为它涉及3个比较和6个投影。即使我们注释掉assert
,投影的数量仍然是4,因为std::invoke(proj, v)
执行了两次。
我能想到的唯一方法是临时存储 的结果std::invoke(proj, v)
,然后将其传递给接下来的两个comp
调用,就像libstdc++一样:
但是为了安全起见,我们似乎无法在第一次调用std::forward<decltype(__proj_val)>(__proj_val)
中完美转发,这意味着我们似乎无法仅使用 3 个投影来完美实现.__proj_val
comp
std::ranges::clamp
为什么要std::ranges::clamp
如此严格地限制投影数量?这是否意味着需要临时存储投影结果以满足复杂性要求?还是我对这种复杂性要求的理解是错误的?
c++ - std::regular_invocable 和按值参数
以下示例是否旨在显示违反先决条件?
std::ranges::transform_view
有限制F fun
它应该是regular_invocable<F&, range_reference_t<V>>
。正如[concept.regularinvocable] regular_invocable
中所写“不得修改函数对象或参数”。所以r2
函数违反了语义约束,因为它通过移动来修改参数。
这种解释有效吗?