为什么范围的算法与 std 的迭代器不兼容?
Why aren't ranges' algorithms compatible with std's iterators?
#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.
对我来说,泛型算法 copy
不应该关心目标迭代器类型,只要它满足输出迭代器的要求即可。
如果是这样,为什么范围的算法与 std 的迭代器不兼容?
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
不会 .
具体来说,ranges::copy()
requires WeaklyIncrementable<O>
which refines SemiRegular<O>
which requires DefaultConstructible
. ranges::ostream_iterator
is default constructible, but std::ostream_iterator
不是。
因此失败。
在 P0896 中,基于范围的 copy()
算法确实需要 WeaklyIncrementable
(因此需要 DefaultConstructible
)作为其输出迭代器 - 但通过还添加来解决这种不匹配std::ostream_iterator
(参见第 70 页)的默认构造函数。
作为对此的更新,P2325R3 刚刚被 C++20 追溯采用,它恢复了这一变化。 std::ostream_iterator
将不再是默认可构造的,weakly_incrementable
概念将不再需要默认可构造性(以及其他更改)。
† 请注意,range-v3/Ranges TS/Ranges 提案概念 OutputIterator 与标准库中现有的 OutputIterator 概念是分开的。 std::ostream_iterator
不模拟前者,但它 做 模拟后者 - 所以今天使用 std::copy
和 std::ostream_iterator
是完全没问题的。 post-P0896,将 ranges::copy
与 std::ostream_iterator
一起使用也可以 - 因为建议更改 std::ostream_iterator
.
#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.
对我来说,泛型算法 copy
不应该关心目标迭代器类型,只要它满足输出迭代器的要求即可。
如果是这样,为什么范围的算法与 std 的迭代器不兼容?
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
不会 .
具体来说,ranges::copy()
requires WeaklyIncrementable<O>
which refines SemiRegular<O>
which requires DefaultConstructible
. ranges::ostream_iterator
is default constructible, but std::ostream_iterator
不是。
因此失败。
在 P0896 中,基于范围的 copy()
算法确实需要 WeaklyIncrementable
(因此需要 DefaultConstructible
)作为其输出迭代器 - 但通过还添加来解决这种不匹配std::ostream_iterator
(参见第 70 页)的默认构造函数。
作为对此的更新,P2325R3 刚刚被 C++20 追溯采用,它恢复了这一变化。 std::ostream_iterator
将不再是默认可构造的,weakly_incrementable
概念将不再需要默认可构造性(以及其他更改)。
† 请注意,range-v3/Ranges TS/Ranges 提案概念 OutputIterator 与标准库中现有的 OutputIterator 概念是分开的。 std::ostream_iterator
不模拟前者,但它 做 模拟后者 - 所以今天使用 std::copy
和 std::ostream_iterator
是完全没问题的。 post-P0896,将 ranges::copy
与 std::ostream_iterator
一起使用也可以 - 因为建议更改 std::ostream_iterator
.