Generators in C++ revisited.
June 25, 2008
Previous version of generators had design problem – it required some special stop value. That is the same kind of problem as with iterators in C++. In some cases it is not possible to choose such a value.
So is this new version:
// generator/continuation for C++
// author: Andrew Fedoniouk @ terrainformatica.com
// idea borrowed from: "coroutines in C" Simon Tatham,
// http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
//++ coroutine, generator, continuation for C++
struct _generator
{
int _line;
_generator():_line(-1) {}
};
#define $generator(NAME) struct NAME : public _generator
#define $emit(T) bool operator()(T& _rv) { \
if(_line < 0) { _line=0;}\
switch(_line) { case 0:;
#define $stop } _line = 0; return false; }
#define $yield(V) \
do {\
_line=__LINE__;\
_rv = (V); return true; case __LINE__:;\
} while (0)
//-- coroutine, generator, continuation for C++
Implementation of typical iterator practically is the same an in previous version except of $stop is being used without any parameter now:
#include "generator.h"
$generator(descent)
{
int i;
$emit(int) // will emit int values. Start of body of the generator.
for (i = 10; i > 0; i–)
$yield(i); // a.k.a. yield in Python,
// returns next number in [1..10], reversed.
$stop; // stop, end of sequence. End of body of the generator.
};
But its usage is a bit different and is close to JavaScript for(var in sequence) statement:
int main(int argc, char* argv[])
{
descent gen;
for(int n; gen(n);) // "get next" generator invocation
printf("next number is %d\n", n);
return 0;
}
And here is version of the generator that supports restart (recursive call) - needed for walking through tree alike (recursive) data structures. It uses allocations on the heap that I think is overkill for such constructions.
Comments (4)
