c – 使用迭代器实现状态机(ala生成器)

最近我需要实现生成一堆数字的小类.如果C有像
python这样的生成器会很方便,但遗憾的是并非如此.

所以我一直在考虑如何最好地实现这些类型的对象,以便于迭代和组合.当我们考虑容器上的迭代器时,它们基本上只将索引保存到元素中,而大部分信息都在容器本身中.这允许多个迭代器同时引用集合中的不同元素.

当它来到状态机时,很明显迭代器必须保持整个状态,因为几个迭代器需要能够独立.从这个意义上讲,状态机类更像是这些迭代器的“构建器”,它们是实际的状态机.

作为玩具示例,我已经实现了范围生成器(python中的ala xrange),可以在循环中使用:

// using range-for from c++11
for (auto i : range<int>(1, 30)) {
    cout << i << endl;
}

代码可以在my bitbucket找到.

也就是说,将整个状态存储在迭代器中是很尴尬的,因为创建end()迭代器只是为了比较结束状态,如果状态是大量成员集合则会浪费空间.

有没有用简单的线性状态机完成任务,并用迭代器循环它们?

最佳答案 如果仅支持前向迭代,则可以使用end()的不同类型然后使用begin().这是基本的想法

class iterator;

class iterator_end {
  typedef ... value_type;
  ...

  iterator& operator++ () { throw ... }
  value_type operator* () { throw ... }
  bool operator== (const iterator& e) const { return e == *this; }
}

class iterator {
  typedef ... value_type;
  ..

  iterator& operator++ () { ... }
  value_type operator* () { ... }
  bool operator== (const iterator_end& e) const { return are_we_done_yet }
}

class statemachine {
  iterator begin() const { ... }
  iterator_end end() const { ... }
}

我从来没有试过这个,所以我不能保证这会起作用.你的状态机的iterator和const_iterator typedef将指定一个与end()返回不同的类型,这可能会也可能不会引起麻烦.

另一种可能性是使用boost :: optional的pimpl变体.将迭代器状态放入一个单独的类中,并将其存储在迭代器中的boost :: optional中.保留为end()返回的迭代器设置的状态.您不会保存任何内存,但是您可以避免堆分配(boost :: optional不执行任何操作,它使用placement new!)和初始化开销.

点赞