为什么范围的算法与 std 的迭代器不兼容?
#include <vector>
#include <iostream>
#include <range/v3/all.hpp>
int main()
{
auto coll = std::vector{ 1, 2, 3 };
ranges::copy(
coll,
ranges::ostream_iterator<int>{ std::cout, ", " }
); // ok
ranges::copy(
coll,
std::ostream_iterator<int>{ std::cout, ", " }
); // error
}
上面的代码显示了问题.我使用 ranges-v3-0.3.7.
The issue is shown in the code above. I use ranges-v3-0.3.7.
对我来说,通用算法 copy
不应该关心目标迭代器类型,只要它满足输出迭代器的要求.
To me, the generic algorithm copy
shouldn't care about the destination iterator type as long as it meets the requirements of output iterator.
如果是这样,为什么范围的算法与 std 的迭代器不兼容?
If so, why aren't ranges' algorithms compatible with std's iterators?
推荐答案
对我来说,通用算法
copy
不应该关心目标迭代器类型,只要它满足输出迭代器的要求.
To me, the generic algorithm
copy
shouldn't care about the destination iterator type as long as it meets the requirements of output iterator.
这是正确的.并不是 ranges::copy
以某种方式识别 ranges::ostream_iterator
而不是 std::ostream_iterator
.就是 Ranges 对 OutputIterator? 的概念有一个完善的概念,例如 ranges::ostream_iterator
对 OutputIterator 进行建模,但 std::ostream_iterator
没有.
This is correct. It's not that ranges::copy
somehow recognizes ranges::ostream_iterator
and not std::ostream_iterator
. It's that Ranges has a refined concept for what an OutputIterator? is, such that ranges::ostream_iterator
does model OutputIterator but std::ostream_iterator
does not.
具体来说,ranges::copy()
需要 WeaklyIncrementable<O>
精炼 SemiRegular
需要 DefaultConstructible
.范围::ostream_iterator
是默认可构造的,但 std::ostream_iterator
不是.
Specifically, ranges::copy()
requires WeaklyIncrementable<O>
which refines SemiRegular<O>
which requires DefaultConstructible
. ranges::ostream_iterator
is default constructible, but std::ostream_iterator
is not.
因此失败了.
在 P0896 中,基于范围的 copy()
算法确实需要 WeaklyIncrementable
(因此也需要 DefaultConstructible
)作为其输出迭代器 - 但通过添加一个std::ostream_iterator
的默认构造函数(参见第 70 页).
In P0896, the range-based copy()
algorithm does require WeaklyIncrementable
(and thus DefaultConstructible
) for its output iterator - but addresses this mismatch by also adding a default constructor to std::ostream_iterator
(see page 70).
作为对此的更新,P2325R3 刚刚被 C++20 追溯采用,它恢复了这一变化.std::ostream_iterator
将不再是默认可构造的,并且 weakly_incrementable
概念将不再需要默认构造(以及其他更改).
As an update to this, P2325R3 was just adopted retroactively for C++20, which reverts this change. std::ostream_iterator
will no longer be default constructible and the weakly_incrementable
concept will no longer require default constructibility (among other changes).
? 请注意,range-v3/Ranges TS/Ranges Proposal 概念 OutputIterator 与标准库现有的 OutputIterator 概念是分开的.std::ostream_iterator
不为前者建模,但它确实 为后者建模 - 因此将 std::copy
与 std 一起使用::ostream_iterator
今天很好.在 P0896 之后,将 ranges::copy
与 std::ostream_iterator
一起使用也可以――因为建议对 std::ostream_iterator
进行更改代码>.
? Note that the range-v3/Ranges TS/Ranges Proposal concept OutputIterator is separate from the standard library's existing concept of OutputIterator. std::ostream_iterator
does not model the former but it does model the latter - so using std::copy
with a std::ostream_iterator
today is perfectly fine. And post-P0896, using ranges::copy
with a std::ostream_iterator
will also be fine - because of the proposed changes to std::ostream_iterator
.
相关文章