简体   繁体   English

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

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

I was looking at generate() and generate_n() in cppreference and am trying to understand why does generate() require ForwardIterator , whereas generate_n() requires OutputIterator for the range? 我在cppreference中查看generate()generate_n()并试图理解为什么generate()需要ForwardIterator ,而generate_n()需要OutputIterator作为范围? (I checked the latest working draft of the Standard, and it's the same requirement.) (我检查了标准的最新工作草案,这是相同的要求。)

Because, at least their possible implementations seem to require identical iterator concepts and OutputIterator seems to be enough: 因为,至少他们可能的实现似乎需要相同的迭代器概念,而OutputIterator似乎就足够了:

generate() : generate()

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

generate_n() : 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;
}

Same story with std::fill() and std::fill_n() . std::fill()std::fill_n()相同的故事。

at least their possible implementations seem to require identical iterator concept and OutputIterator seems to be enough 至少他们可能的实现似乎需要相同的迭代器概念,而OutputIterator似乎就足够了

OutputIterator doesn't support equality / inequality comparison (including operator!= used in the possible implementation of generate() you showed) and multipass guarantee, while ForwardIterator does. OutputIterator不支持相等/不等式比较(包括operator!=在您显示的generate()的可能实现中使用)和多通道保证,而ForwardIterator则支持。 That means OutputIterator can't be used for representing a range via two iterators (eg [first, last) ) which is required by generate() 's interface. 这意味着OutputIterator不能用于通过两个迭代器(例如[first, last) )来表示范围[first, last)这是generate()接口所需要的。

Equality and inequality may not be defined for output iterators. 可能没有为输出迭代器定义平等和不平等。 Even if an operator== is defined, x == y need not imply ++x == ++y. 即使定义了运算符==,x == y也不需要暗示++ x == ++ y。

songyuanyao's answer explains the matter from a technical viewpoint. songyuanyao的回答从技术角度解释了这个问题。 I'll try to provide a bit more informal explanation. 我会尝试提供一些非正式的解释。

Many STL algorithms, including generate and fill , are applied to a number of items. 许多STL算法(包括generatefill )都应用于许多项目。 The way an algorithm must be able to access those items defines the requirements for the iterator. 算法必须能够访问这些项的方式定义了迭代器的要求。

In your case, the definition of generate contains: 在您的情况下, generate的定义包含:

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

While the second requirement seems to be satisfied by any iterator type (after all, that's what iterators are all about — iterating over things :)), the support for comparison operator!= is provided by not all iterator types. 虽然第二个要求似乎满足任何迭代器类型(毕竟,这就是迭代器的全部内容 - 迭代事物:)),并非所有迭代器类型都提供对比较运算符operator!=的支持。

For instance, you cannot use ostream_iterator for std::generate . 例如,您不能将ostream_iterator用于std::generate But, you can, eg , output a fixed number of generated values into a stream via std::generate_n . 但是,可以, 例如 ,输出固定数量的产生的值转换成经由流std::generate_n

Here's a very artificial example at Coliru . 这是Coliru一个非常人为的例子 Once I start thinking about real-life applications, I'd guess the ability to work with OutputIterators may be useful for implementing some serialization logic. 一旦我开始考虑实际应用程序,我猜想使用OutputIterators的能力可能对实现一些序列化逻辑很有用。

generate() and generate_n() , like all the standard library algorithms, operate on a range , that is, a sequence of values accessed through an iterator. 与所有标准库算法一样, generate()generate_n()在一个范围上运行 ,即通过迭代器访问的一系列值。 In order to apply an operation to all of the elements of a range the algorithm has to know where the range begins and where it ends. 为了将操作应用于范围的所有元素,算法必须知道范围的开始位置和结束位置。 There are two common ways of giving it that information: you can specify the range with an iterator and a length, and use a loop of the form while (length-- != 0) { ... ++first; } 给它提供信息的常用方法有两种:你可以用迭代器和长度指定范围,并使用形式的循环while (length-- != 0) { ... ++first; } while (length-- != 0) { ... ++first; } ; while (length-- != 0) { ... ++first; } ; or you can specify the range with a pair of iterators [first, last) and use a loop of the form while (first != last) { ... ++first; } 或者您可以使用一对迭代器[first, last)指定范围并使用形式的循环while (first != last) { ... ++first; } while (first != last) { ... ++first; } . while (first != last) { ... ++first; }

For the first version, you need to be able to increment the iterator and, for these algorithms, write a value through the iterator. 对于第一个版本,您需要能够递增迭代器,并且对于这些算法,通过迭代器写入值。 Those are the main properaties of a output iterator , and that's all you need for generate_n() . 这些是输出迭代器的主要优点,而这就是generate_n()需要的。

For the second version, you need to be able to increment the iterator and write a value through the iterator, just like the first version. 对于第二个版本,您需要能够增加迭代器并通过迭代器写入值,就像第一个版本一样。 You also have to be able to compare two iterators for equality, and an output iterator doesn't support that; 必须能够比较两个迭代器的相等性,并且输出迭代器不支持它; you have to have at least a forward iterator . 你必须至少拥有一个前向迭代器 That's why generate() , which takes a range designated by a pair of iterators, requires a forward iterator. 这就是为什么generate() ,它采用一对迭代器指定的范围,需要一个前向迭代器。

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

相关问题 使用std :: generate_n填充std :: map - Fill std::map with std::generate_n 带列表的std :: generate_n函数 - std::generate_n function with list 用于std :: generate_n的并行执行可变lambda生成器 - Parallel execution mutable lambda generator for std::generate_n 使用std :: generate_n使用字母字符填充向量 - Fill a vector with alphabet chars using std::generate_n 通过std :: generate_n()算法使用自定义仿函数的正确方法? - Correct way to use custom functor with std::generate_n() algorithm? std::generate_n 的返回值迭代器,你能用它做什么? - return value iterator of std::generate_n, what can you do with it? 这是组合std :: generate_n和std :: back_inserter的正确方法吗? - Is this correct way to combine std::generate_n and std::back_inserter? 如何将std :: generate / generate_n与多态函数对象一起使用? - How can I use std::generate/generate_n with a polymorphic function object? std :: generate_n的函子能够安全地捕获和操作用于填充的容器吗? - Is it safe for std::generate_n's functor to capture and operate on container it's used for populating? 通过引用传递 function object 在 std::generate_n() 中不起作用 - Passing function object by reference doesn't work in std::generate_n()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM