【问题标题】:Why does std::fill use ForwardIterator, not OutputIterator?为什么 std::fill 使用 ForwardIterator,而不是 OutputIterator?
【发布时间】:2017-04-19 23:43:21
【问题描述】:

(此问题与Why does std::max_element require a ForwardIterator? 具有相同的“问题模板”,但答案必须不同,因为std::fill 不会将迭代器返回到输出序列中。)

std::fill 被定义为仅在输出范围由一对 ForwardIterators 给出时才起作用。然而,表面上相似的std::fill_n 可以很好地与 OutputIterator 配合使用。

算法肯定很简单

template<class OutIt, class T>
void fill(OutIt first, OutIt last, T value)
{
    while (first != last) {
        *first = value;
        ++first;
    }
}

这个算法需要 ForwardIterator 怎么样?我错过了什么?

【问题讨论】:

    标签: c++ stl iterator


    【解决方案1】:

    输出迭代器不可比较。没有为输出迭代器定义 ==!= 运算符。

    你需要一个前向迭代器,因为它

    满足输入迭代器的要求

    支持EqualityComparable

    使用输出迭代器,std::fill 无法将 firstlast 进行比较:

    while (first != last) {
    

    不支持,用于输出迭代器。

    std::fill_n 避免了这种比较,它只是使用计数器写入迭代器,所以它只需要一个输出迭代器。

    【讨论】:

    • 哦,这是关于平等可比性的。恕我直言,不幸的是,当前的标准概念将“平等可比”的概念和“输入可迭代”的概念联系在一起——我认为有类似 class SentineledOstreamIterator 的东西是可比较的 o1 == o2 和可分配*o1 = v,但您仍然不被允许从中读取v = *o1。但是好吧,有了当前的概念层次结构,我明白为什么 OutputIterator 没有受到足够的约束。
    • @Quuxplusone 通用输出迭代器具有可比性是没有意义的;例如想象一下,如果输出迭代器正在输出到连接到终端的ofstream。比较其中两个是什么意思?
    • 我想比较一般的 istream 迭代器也没有意义,尽管按顺序与单数迭代器(表示文件结束或错误)进行比较是有用的读取流的剩余部分;而对于输出,没有“写到文件结束”之类的东西
    • @M.M(第二条评论):完全正确! 通常输入和输出迭代器不可比较,但有时可以。例如,ostream_iterator::operator== 的语义可能类似于istream_iterator::operator==,即在底层流上返回(!x.ready() &amp;&amp; !y.ready()) || (&amp;x == &amp;y)。当然,这主要适用于想要“写入相同字节直到出现磁盘错误或文件系统已满”的程序,这可能是一种不常见的情况。 ;)
    【解决方案2】:

    OutputIterator 没有“范围”的概念。因此,您必须提供重复计数。使用ForwardIterator,您可以处理一系列元素。

    这些是语义不同的东西。 fill_n 用于从提供的迭代器开始添加一些元素。 fill 用于更改元素范围。

    以插入器(例如back_inserter)为例。你可以插入比容器中更多的元素,所以last 甚至没有意义。

    OutputIterator 为您提供了一个可以放入对象的地方。 ForwardIterator 对象必须存在。

    来自cppreference

    带有输出迭代器的 operator* 唯一有效的用法是在赋值的左侧:operator* 可能返回一个代理对象,该对象定义了一个成员 operator=(可能是一个模板)

    这意味着您基本上无法从中读取,这与ForwardIterator相反:

    ForwardIterator 是一个可以从指向的元素中读取数据的迭代器。

    【讨论】:

    • 我认为您的编辑实际上将这个答案从“好”变为“更差”。 std::fill 不会尝试从其迭代器参数中读取;它确实仅在作业的左侧使用*x。因此,引入这个事实会激发我的问题,但它无助于回答它。
    • 是否可以引用另一句话来对比 ForwardIterator 必须 可读以提供帮助?我知道fill 不读取元素,但这没关系。它旨在处理一系列元素。我不确定您是否不了解迭代器类型之间的区别,或者不了解使您提议的实现无法实现的技术性。我针对前者。后者在另一个答案中进行了解释。也许这个将来对其他人有用。
    猜你喜欢
    • 1970-01-01
    • 2017-07-22
    • 2011-08-03
    • 1970-01-01
    • 2019-04-14
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    相关资源
    最近更新 更多