等效的C ++到Python生成器模式 [英] Equivalent C++ to Python generator pattern
问题描述
我有一些示例Python代码,我需要在C ++中模仿。我不需要任何具体的解决方案(如基于协同程序的产出解决方案,虽然他们也是可以接受的答案),我只需要以某种方式重现语义。
I've got some example Python code that I need to mimic in C++. I do not require any specific solution (such as co-routine based yield solutions, although they would be acceptable answers as well), I simply need to reproduce the semantics in some manner.
这是一个基本的序列生成器,显然太大,无法存储实体化版本。
This is a basic sequence generator, clearly too large to store a materialized version.
def pair_sequence():
for i in range(2**32):
for j in range(2**32):
yield (i, j)
目标是保持上面序列的两个实例,半锁步,但在块。在下面的示例中, first_pass
使用成对的序列来初始化缓冲区, second_pass
The goal is to maintain two instances of the sequence above, and iterate over them in semi-lockstep, but in chunks. In the example below the first_pass
uses the sequence of pairs to initialize the buffer, and the second_pass
regenerates the same exact sequence and processes the buffer again.
def run():
seq1 = pair_sequence()
seq2 = pair_sequence()
buffer = [0] * 1000
first_pass(seq1, buffer)
second_pass(seq2, buffer)
... repeat ...
C ++
我可以找到一个解决方案在C ++中,只是模仿 yield
与C ++协程,但我没有找到任何有关如何做到这一点的好的参考。我也对这个问题的替代(非一般)解决方案感兴趣。我没有足够的内存预算来保存传递之间的序列副本。
C++
The only thing I can find for a solution in C++ is to mimic yield
with C++ coroutines, but I haven't found any good reference on how to do this. I'm also interested in alternative (non general) solutions for this problem. I do not have enough memory budget to keep a copy of the sequence between passes.
推荐答案
生成器存在于C ++中, name: Input Iterators 。例如,从 std :: cin
读取类似于具有 char
的生成器。
Generators exist in C++, just under another name: Input Iterators. For example, reading from std::cin
is similar to having a generator of char
.
您只需要了解一个生成器的功能:
You simply need to understand what a generator does:
- 有一个数据块:变量定义状态
- 有一个init方法
- 有一个下一个方法
- 有一种信号终止方式。
- there is a blob of data: the local variables define a state
- there is an init method
- there is a "next" method
- there is a way to signal termination
在一个简单的例子中,概念上:
In your trivial example, it's easy enough. Conceptually:
struct State { unsigned i, j; };
State make();
void next(State&);
bool isDone(State const&);
当然,我们将其封装为一个合适的类:
Of course, we wrap this as a proper class:
class PairSequence {
typedef void (PairSequence::*BoolLike)();
void non_comparable();
public:
typedef std::input_iterator_tag iterator_category;
typedef std::pair<unsigned, unsigned> value_type;
typedef value_type const& reference;
typedef value_type const* pointer;
typedef ptrdiff_t difference_type;
PairSequence(): done(false) {}
// Safe Bool idiom
operator BoolLike() const {
return done ? nullptr : &PairSequence::non_comparable;
}
reference operator*() const { return ij; }
pointer operator->() const { return &ij; }
PairSequence& operator++() {
static unsigned const Max = std::numeric_limts<unsigned>::max();
assert(!done);
if (ij.second != Max) { ++ij.second; return *this; }
if (ij.first != Max) { ij.second = 0; ++ij.first; return *this; }
done = true;
return *this;
}
PairSequence operator++(int) {
PairSequence const tmp(*this);
++*this;
return tmp;
}
private:
bool done;
value_type ij;
};
所以哼哼哼...可能C ++比较繁琐:)
So hum yeah... might be that C++ is a tad more verbose :)
这篇关于等效的C ++到Python生成器模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!