问题标签 [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 投票
0 回答
101 浏览

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::rangeconst D不是 a 的情况ranges::range

0 投票
2 回答
108 浏览

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

为什么标准指定对基础值使用大括号初始化,即使它可能会导致不一致?这背后的考虑是什么?

0 投票
0 回答
47 浏览

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) | ...。这是可能的吗?

0 投票
3 回答
141 浏览

c++ - 在什么情况下 ref_view{E} 格式错误而 subrange{E} 不是?

C++20 引入了views::allwhich 是一个范围适配器,它返回view包含其范围参数的所有元素的 a。

该表达式views::all(E)与以下表达式等效(具有相同的效果):

  • decay-copy(E)如果是腐烂类型的E模型view
  • 否则,ref_view{E}如果该表达式是格式良好的
  • 否则,subrange{E}

第一种情况表示 a的类型在使用(goldbotview )管道后没有改变:views::all

第二种情况用于包装viewable_rangewithref_view以方便范围管道操作:

但是关于第三种情况,我想不出在什么情况下subrange{E}是良构和ref_view{E}良构。

它的目的是什么?有人可以举个例子吗?

0 投票
2 回答
292 浏览

c++ - 是否可以从 C++20 中的视图构造一个`std::span`?

此示例程序无法编译,因为transform_view无法转换为std::span

我知道还不能构造容器(如std::vector),但是我不太明白,为什么不能从中构造 a std::span。我找到了这个答案,也就是说,目前唯一可以从任意范围构造的容器是std::span,所以我希望上面的示例能够工作。

有没有办法从一个范围创建一个跨度?或者有没有其他方法可以从方法返回通用视图,而不使用auto(虚拟方法不允许这样做)?

0 投票
2 回答
123 浏览

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()如果被缓存,是否有任何潜在的缺陷?

0 投票
3 回答
320 浏览

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?例如,如果Irandom_asscess_iterator,那么common_iterator<I, S>random_asscess_iterator,等等。

似乎这在技术上是可行的,因为common_iterator仅用于std::variant键入擦除IS.

考虑以下(godbolt):

rrandom_access_range,所以 C++20 约束算法比如ranges::binary_search可以使用这个 trait 对其执行更高效的操作,但是为了使旧std算法能够应用它,我们需要使用views::common将它转换为common_range. 但是,它也会退化为 a forward_range,这会降低算法的效率。

为什么标准最多只定义common_iteratorforward_iterator?这背后的考虑是什么?

0 投票
2 回答
842 浏览

c++ - c++20 范围的意义何在?

与老式的迭代器相比,我很难理解 c++20 范围增加了什么。是的,我想没有必要再使用beginandend了,而是简单的重载,例如:

会解决这个问题。

与迭代器相比,范围为什么有用?什么时候应该使用它们?

编辑:我知道范围比迭代器有其他优势(链接,更好的方法等......)。然而,这些(我认为?)都可以用迭代器来完成,我不明白为什么需要引入一个全新的概念,比如范围。

0 投票
1 回答
276 浏览

c++ - 为什么views::reverse 不适用于iota_view

我有以下 C++ 程序,由于某种原因,我不能int64_t用作模板参数。

这是预期的(我做错了什么),还是只是编译器/标准库中的一些不幸的错误?

注意:当我删除std::views::reverse代码时int64_t也会编译。

0 投票
0 回答
105 浏览

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()viewinner-iteratordefault_sentinel_tbegin()

该函数根据其类型 是否begin()为 来选择是否移动底层,这看起来很合理。i_outer-iteratorcopyable

但是,这个约束似乎没用,原因是outer-iterator似乎总是满足copyable. 在[range.adaptors#range.split.outer]中,outer-iterator作为 的迭代器类型的split_view被定义为:

当基类型Vsplit_view模型forward_range如 时input_rangeouter-iterator只包含一个指针,所以它显然是copyable。当V是 aforward_range时, thecurrent_也是 a forward_iterator, 所以它是copyable, 这 使得outer-iteratorcopyable

那么为什么标准需要基于一个永远无法满足的约束来定义一个begin()函数呢?split_view::outer-iterator::value_type

查了之前的论文,没有发现关于这部分的讨论,不过这个begin()功能好像是在LWG3276之后添加的。