【问题标题】:How could I make my own lazy iterator?我怎样才能制作自己的惰性迭代器?
【发布时间】:2012-06-28 16:01:46
【问题描述】:

我正在制作一个产生大量数据的 C++11 类。该数据当前来自数据库,无法完全放入内存。我想为用户提供一个行为类似于常规 STL 迭代器的迭代器,但这会很懒惰。更准确地说,我可以做这样的事情:

for (auto& item : big_bunch_of_data) {
    do_stuff_with(item);
}

只有在每次迭代时才从数据库中检索项目。如果我是对的,这种新语法是

的糖
for (stuff::iterator it = big_bunch_of_data.begin();it != big_bunch_of_data.end();it++) {
    do_stuff_with(*it);
}

这是否意味着通过提供beginendoperator++,我可以获得所需的行为?而且,这些方法应该做什么?我的意思是,我可以在不破坏东西的情况下让他们变得懒惰吗?

【问题讨论】:

  • “该数据当前来自数据库,无法完全放入内存” 因此,在不了解您的数据库的情况下很难给出更好的建议……但请记住许多 SQL 数据库以 cursors 的形式提供自己的内部迭代器机制,这可能对您有用。
  • 我正在使用 sqlite,但将来可能会改变,我不想将原始指针暴露给我的代码的用户,这就是为什么我试图封装它相当不错(是的,已经很懒了)API。

标签: c++ c++11 iterator lazy-evaluation


【解决方案1】:

几乎;如果在容器类上找不到beginend 方法,编译器将在其他几个地方查找开始和结束迭代器;这就是基于范围的 for 循环在没有 beginend 成员的数组上的工作方式。它还将寻找由 ADL 提供的免费函数 beginend,并最终寻找 std::beginstd::end,因此有很多机会来改进现有容器的基于范围的 for 循环支持。 Section 6.5.4 涵盖了细节。

对于您的其他问题,迭代器绝对可以是懒惰的!一个很好的例子是std::istream_iterator,它必须在从控制台读取输入时变得懒惰。

for 循环中使用迭代器的要求是它应该满足section 24.2.3 中描述的输入迭代器 类别;该类别所需的操作是!=,一元*,以及前后增量++

要让语言知道您已经创建了一个输入迭代器,您应该从 std::iterator<std::input_iterator_tag, T, void, T *, T &> 继承,其中 T 是您的迭代器处理的类型 (section 24.4.3)。

【讨论】:

  • 其实,没有。它直接使用.begin() 成员函数。如果没有找到这样的成员,它通过 ADL 使用begin,不一定是std::begin
猜你喜欢
  • 2021-06-06
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
  • 2021-11-21
  • 2017-01-15
  • 2020-04-12
  • 2014-06-22
相关资源
最近更新 更多