最近我需要实现生成一堆数字的小类。如果C ++有像python这样的生成器,那将是非常方便的,但遗憾的是并非如此。
所以我一直在考虑如何最好地实现这些类型的对象,以便于迭代和组合。当我们考虑容器上的迭代器时,它们基本上只将索引保存到元素中,而大部分信息都在容器本身中。这允许多个迭代器同时引用集合中的不同元素。
当它来到状态机时,很明显迭代器必须保持整个状态,因为几个迭代器需要能够独立。从这个意义上讲,状态机类更像是这些迭代器的“构建器”,它们是实际的状态机。
作为玩具示例,我已经实现了范围生成器(python中的ala xrange
),可以在循环中使用:
// using range-for from c++11
for (auto i : range<int>(1, 30)) {
cout << i << endl;
}
代码可以在my bitbucket找到。
也就是说,将整个状态存储在迭代器中是很尴尬的,因为创建end()
迭代器只是为了比较结束状态,如果状态是大量成员,则会浪费空间
使用简单的线性状态机完成了什么,并用迭代器循环它们吗?
答案 0 :(得分:2)
如果仅支持前向迭代,则可以使用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!)和初始化开销。