13
#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 
}

该问题显示在上面的代码中。我使用range-v3-0.3.7

对我来说,通用算法copy不应该关心目标迭代器类型,只要它满足输出迭代器的要求。

如果是这样,为什么范围的算法与 std 的迭代器不兼容?

4

1 回答 1

24

对我来说,通用算法copy不应该关心目标迭代器类型,只要它满足输出迭代器的要求。

这是对的。这不是以ranges::copy某种方式识别ranges::ostream_iterator而不是std::ostream_iteratorRanges 对 OutputIterator †</sup> 是什么有一个精炼的概念,这样可以对 OutputIterator 进行建模但没有ranges::ostream_iteratorstd::ostream_iterator

具体来说,ranges::copy()需要WeaklyIncrementable<O>哪个精炼SemiRegular<O>哪个需要DefaultConstructibleranges::ostream_iterator是默认可构造的,但std::ostream_iterator不是。

因此失败。


P0896中,基于范围的copy()算法确实需要WeaklyIncrementable(因此DefaultConstructible)其输出迭代器 - 但通过添加默认构造函数来解决此不匹配问题std::ostream_iterator(参见第 70 页)。


作为对此的更新,P2325R3刚刚被 C++20 追溯采用,这恢复了这一变化。std::ostream_iterator将不再是默认可构造的,并且该weakly_incrementable概念将不再需要默认可构造性(以及其他更改)。


†</sup> 请注意,range-v3/Ranges TS/Ranges Proposal 概念 OutputIterator 与标准库现有的 OutputIterator 概念是分开的。std::ostream_iterator不为前者建模,但它确实为后者建模 - 因此std::copystd::ostream_iterator今天一起使用非常好。在 P0896 之后,使用ranges::copywith astd::ostream_iterator也可以 - 因为建议更改std::ostream_iterator.

于 2018-09-21T02:28:24.213 回答