为什么 std::generate() 和 std::generate_n() 需要不同的迭代器?
Why do std::generate() and std::generate_n() require different iterators?
我在cpp首选项中查看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
似乎就足够了
输出迭代器不支持相等/不平等比较(包括您展示的generate()
的可能实现中使用的operator!=
(和多通道保证,而前向迭代器支持。这意味着OutputIterator
不能用于通过两个迭代器表示范围(例如[first, last)
(,这是generate()
的接口所必需的。
不能为输出迭代器定义相等和不相等。即使定义了运算符 ==,x == y 也不必暗示 ++x == ++y。
松元尧的回答从技术角度解释了这个问题。我将尝试提供更非正式的解释。
许多STL算法,包括generate
和fill
,被应用于许多项目。算法必须能够访问这些项的方式定义了迭代器的要求。
在您的情况下,generate
的定义包含:
...
while (first != last) { // implies that Iter implements operator!=
*first++; // implies that Iter implements operator++
虽然任何迭代器类型似乎都满足第二个要求(毕竟,这就是迭代器的全部内容 - 迭代事物:)(,但并非所有迭代器类型都提供对比较operator!=
的支持。
例如,您不能将ostream_iterator
用于std::generate
。但是,例如,您可以通过std::generate_n
将固定数量的生成值输出到流中。
这是科利鲁的一个非常人为的例子。一旦我开始考虑实际的应用程序,我就会猜测使用输出迭代器的能力对于实现一些序列化逻辑可能很有用。
generate()
和generate_n()
与所有标准库算法一样,在一个范围上运行,即通过迭代器访问的值序列。为了将操作应用于范围的所有元素,算法必须知道范围从哪里开始,在哪里结束。有两种常见的方法可以为其提供该信息:您可以使用迭代器和长度指定范围,并使用形式为while (length-- != 0) { ... ++first; }
的循环;或者,您可以使用一对迭代器[first, last)
指定范围,并使用形式为while (first != last) { ... ++first; }
的循环。
对于第一个版本,您需要能够递增迭代器,对于这些算法,通过迭代器写入值。这些是输出迭代器的主要属性,这就是您generate_n()
所需要的。
对于第二个版本,您需要能够递增迭代器并通过迭代器写入值,就像第一个版本一样。您还必须能够比较两个迭代器的相等性,而输出迭代器不支持这一点;您必须至少有一个前向迭代器。这就是为什么generate()
需要一个由一对迭代器指定的范围,需要一个前向迭代器。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 'generate'不是窗口头文件中'std::random_device'的成员<random>
- C++: std::generate in constructor
- 为什么 std::generate() 和 std::generate_n() 需要不同的迭代器?
- 如何修改 std::generate 的绑定成员函数的结果
- 使用 'std::generate' 或 'std::fill' 来填充 'arma::mat'
- 我可以使用 std::generate 来获取 std::array<T, 2> 的向量吗?
- std::transform 或 std::generate 在没有 ExecutionPolicy 的情况下是否可以并
- C++ std::generate 函数总是给出相同的值
- C++11 std::generate 和 std::uniform_real_distribution 调用两次会产生
- 为什么std::generate在没有命名空间限定符的情况下是可访问的
- 为什么 std::generate 将与 lambda 生成器一起使用,而 std::fill 则不能
- std::generate-如何使用随机数生成器
- Std::generate不能在Std::vector上工作
- 提供给std::generate的Can函数是有状态的
- 对于std::generate,可以传递函数use index