繁体   English   中英

为什么std :: generate()和std :: generate_n()需要不同的迭代器?

[英]Why do std::generate() and std::generate_n() require different iterators?

我在cppreference中查看generate()generate_n()并试图理解为什么generate()需要ForwardIterator ,而generate_n()需要OutputIterator作为范围? (我检查了标准的最新工作草案,这是相同的要求。)

因为,至少他们可能的实现似乎需要相同的迭代器概念,而OutputIterator似乎就足够了:

generate()

template<class ForwardIt, class Generator>
void generate(ForwardIt first, ForwardIt last, Generator g)
{
    while (first != last) {
        *first++ = g();
    }
}

generate_n()

template<class OutputIt, class Size, class Generator>
OutputIt generate_n(OutputIt first, Size count, Generator g)
{
    for (Size i = 0; i < count; i++) {
        *first++ = g();
    }
    return first;
}

std::fill()std::fill_n()相同的故事。

至少他们可能的实现似乎需要相同的迭代器概念,而OutputIterator似乎就足够了

OutputIterator不支持相等/不等式比较(包括operator!=在您显示的generate()的可能实现中使用)和多通道保证,而ForwardIterator则支持。 这意味着OutputIterator不能用于通过两个迭代器(例如[first, last) )来表示范围[first, last)这是generate()接口所需要的。

可能没有为输出迭代器定义平等和不平等。 即使定义了运算符==,x == y也不需要暗示++ x == ++ y。

songyuanyao的回答从技术角度解释了这个问题。 我会尝试提供一些非正式的解释。

许多STL算法(包括generatefill )都应用于许多项目。 算法必须能够访问这些项的方式定义了迭代器的要求。

在您的情况下, generate的定义包含:

...
while (first != last) {  // implies that Iter implements operator!=
  *first++;              // implies that Iter implements operator++

虽然第二个要求似乎满足任何迭代器类型(毕竟,这就是迭代器的全部内容 - 迭代事物:)),并非所有迭代器类型都提供对比较运算符operator!=的支持。

例如,您不能将ostream_iterator用于std::generate 但是,可以, 例如 ,输出固定数量的产生的值转换成经由流std::generate_n

这是Coliru一个非常人为的例子 一旦我开始考虑实际应用程序,我猜想使用OutputIterators的能力可能对实现一些序列化逻辑很有用。

与所有标准库算法一样, generate()generate_n()在一个范围上运行 ,即通过迭代器访问的一系列值。 为了将操作应用于范围的所有元素,算法必须知道范围的开始位置和结束位置。 给它提供信息的常用方法有两种:你可以用迭代器和长度指定范围,并使用形式的循环while (length-- != 0) { ... ++first; } while (length-- != 0) { ... ++first; } ; 或者您可以使用一对迭代器[first, last)指定范围并使用形式的循环while (first != last) { ... ++first; } while (first != last) { ... ++first; }

对于第一个版本,您需要能够递增迭代器,并且对于这些算法,通过迭代器写入值。 这些是输出迭代器的主要优点,而这就是generate_n()需要的。

对于第二个版本,您需要能够增加迭代器并通过迭代器写入值,就像第一个版本一样。 必须能够比较两个迭代器的相等性,并且输出迭代器不支持它; 你必须至少拥有一个前向迭代器 这就是为什么generate() ,它采用一对迭代器指定的范围,需要一个前向迭代器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM