问题标签 [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++ - 为什么 view_interface::data const 重载需要额外检查 const D 是否满足 range::range?
根据[view.interface],非 const 和 const 重载data
函数定义如下:
为什么data() const
需要另外满足那const D
是一个ranges::range
?是不是iterator_t<const D>
已经被限制了,所以那const D
一定是一个ranges::range
?
来这里的真正目的是requires range<const D>
什么?是否存在D
是 aranges::range
而const D
不是 a 的情况ranges::range
?
c++ - 为什么 range::single_view 对基础值使用花括号初始化?
根据[range.single.view#3], std::ranges::single_view
构造函数之一定义为:
效果
value_
:如同按初始化value_{in_place, std::forward<Args>(args)...}
。
为什么标准指定使用直接列表初始化({}
)来初始化value_
?为什么不使用直接初始化( ()
) 就像std::optional
,std::variant
和一样std::any
?
此外,std::constructible_from
( std::is_constructible
) 指定T obj(std::declval<Args>()...)
是合式的,而不是T obj{std::declval<Args>()...}
。
考虑以下内容:
因为使用了不同的初始化,所以#1
会调用std::vector<int>{0, 100}
和打印2
,#2
会调用std::vector<int>(0, 100)
和打印100
。
为什么标准指定对基础值使用大括号初始化,即使它可能会导致不一致?这背后的考虑是什么?
c++ - C++20 范围库中范围适配器的迭代器转换器
我正在研究 C++20 的范围库,我想知道从一个函数template<Iterator I,Iterator J> I f(J)
(或者可能是它的一个更受限制的版本)构建一个范围适配器有多容易。我想到的特定示例是对std::function<I()>
s 流的并发评估。我想到的功能可能是这样的:
然后我想要一个as_adaptor
函数,以便我可以说... | transform([](int x) { return [x](){return x+1};}) | as_adaptor(async_eval) | ...
。这是可能的吗?
c++ - 在什么情况下 ref_view{E} 格式错误而 subrange{E} 不是?
C++20 引入了views::all
which 是一个范围适配器,它返回view
包含其范围参数的所有元素的 a。
该表达式views::all(E)
与以下表达式等效(具有相同的效果):
decay-copy(E)
如果是腐烂类型的E
模型view
。- 否则,
ref_view{E}
如果该表达式是格式良好的 - 否则,
subrange{E}
第一种情况表示 a的类型在使用(goldbotview
)管道后没有改变:views::all
第二种情况用于包装viewable_range
withref_view
以方便范围管道操作:
但是关于第三种情况,我想不出在什么情况下subrange{E}
是良构和ref_view{E}
良构。
它的目的是什么?有人可以举个例子吗?
c++ - 是否可以从 C++20 中的视图构造一个`std::span`?
此示例程序无法编译,因为transform_view
无法转换为std::span
:
我知道还不能构造容器(如std::vector
),但是我不太明白,为什么不能从中构造 a std::span
。我找到了这个答案,也就是说,目前唯一可以从任意范围构造的容器是std::span
,所以我希望上面的示例能够工作。
有没有办法从一个范围创建一个跨度?或者有没有其他方法可以从方法返回通用视图,而不使用auto
(虚拟方法不允许这样做)?
c++ - 为什么 range::basic_istream_view::begin() 没有被缓存?
我发现 c++20与range-v3版本ranges::basic_istream_view
略有不同。
最重要的区别是sstd::ranges::basic_istream_view
不缓存其begin()
,因此每个begin()
s 将返回具有已读取值的下一个迭代器(Godbolt):
考虑以下(godbolt),如果我使用 range-v3 版本,所有三个std::ranges::find()
s 都会找到"is"
,但如果我使用 std 版本,"is"
只会在第一次调用中找到。
为什么标准选择了与 range-v3 不同的设计?begin()
如果被缓存,是否有任何潜在的缺陷?
c++ - 为什么 std::common_iterator 只是 std::forward_iterator?
C++20 引入了一个std::common_iterator
能够将非公共元素范围(迭代器和哨兵的类型不同)表示为公共范围(它们相同)的元素,其概要定义为:
它对于与期望范围的开始和结束具有相同类型的遗留代码交互很有用。
在[iterators.common#common.iter.types-1.1]中,其iterator_concept
定义为:
iterator_concept
表示forward_iterator_tag
如果I
模型forward_iterator
;否则表示input_iterator_tag
。
为什么common_iterator
最多只能是 a forward_iterator
,而不能完全iterator_concept
基于I
's来定义它iterator_category
?例如,如果I
是random_asscess_iterator
,那么common_iterator<I, S>
是random_asscess_iterator
,等等。
似乎这在技术上是可行的,因为common_iterator
仅用于std::variant
键入擦除I
和S
.
考虑以下(godbolt):
r
是random_access_range
,所以 C++20 约束算法比如ranges::binary_search
可以使用这个 trait 对其执行更高效的操作,但是为了使旧std
算法能够应用它,我们需要使用views::common
将它转换为common_range
. 但是,它也会退化为 a forward_range
,这会降低算法的效率。
为什么标准最多只定义common_iterator
为forward_iterator
?这背后的考虑是什么?
c++ - c++20 范围的意义何在?
与老式的迭代器相比,我很难理解 c++20 范围增加了什么。是的,我想没有必要再使用begin
andend
了,而是简单的重载,例如:
会解决这个问题。
与迭代器相比,范围为什么有用?什么时候应该使用它们?
编辑:我知道范围比迭代器有其他优势(链接,更好的方法等......)。然而,这些(我认为?)都可以用迭代器来完成,我不明白为什么需要引入一个全新的概念,比如范围。
c++ - 为什么views::reverse 不适用于iota_view
我有以下 C++ 程序,由于某种原因,我不能int64_t
用作模板参数。
这是预期的(我做错了什么),还是只是编译器/标准库中的一些不幸的错误?
注意:当我删除std::views::reverse
代码时int64_t
也会编译。
c++ - 什么情况下ranges::split_view的迭代器不满足copyable?
C++20 引入了 a ranges::split_view
,它接受 aview
和分隔符,并view
根据分隔符将其拆分为子范围。
分隔符也是a view
,当它是单个元素时,它会被包裹在a中ranges::single_view
。
每个返回的子范围也是一个view
,它的类型是split_view::outer-iterator::value_type
,在[range.adaptors#range.split.outer.value]中定义:
这个内部的begin()
and的返回类型是and ,但这对问题并不重要。问题在于这里的两个约束函数:end()
view
inner-iterator
default_sentinel_t
begin()
该函数根据其类型 是否begin()
为 来选择是否移动底层,这看起来很合理。i_
outer-iterator
copyable
但是,这个约束似乎没用,原因是outer-iterator
似乎总是满足copyable
. 在[range.adaptors#range.split.outer]中,outer-iterator
作为 的迭代器类型的split_view
被定义为:
当基类型V
不split_view
模型forward_range
如 时input_range
,outer-iterator
只包含一个指针,所以它显然是copyable
。当V
是 aforward_range
时, thecurrent_
也是 a forward_iterator
, 所以它是copyable
, 这 使得outer-iterator
也copyable
。
那么为什么标准需要基于一个永远无法满足的约束来定义一个begin()
函数呢?split_view::outer-iterator::value_type
查了之前的论文,没有发现关于这部分的讨论,不过这个begin()
功能好像是在LWG3276之后添加的。