По следам плодотворной дискусии про итераторы...
Используя идею
"coroutines in C" Simon Tatham вот родилось следующее решение для C++.
Прежде всего пример генератора:
#include "generator.h"
generator(desc)
{
int i;
emit(int) // будем выдавать int'ы
for (i = 10; i > 0; --i)
yield(i); // a.k.a. yield in Python - return next number in [10..1]
stop(0); // все, конец последовательности.
};
При вызове оного "оператор" yield выдает следуещее число последовательности. Используется например так:
Пока есть следующее число печатаем его:
int main(int argc, char* argv[])
{
desc gen;
do
printf("got number %d\n", gen());
while (gen);
return 0;
}
Вот весь исходник generator.h:
// 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
#ifndef __generator_h_
#define __generator_h_
struct _generator
{
int _line;
_generator():_line(-1) {}
operator bool() const { return _line != 0; }
};
#define generator(NAME) struct NAME : public _generator
#define emit(T) T operator()() { \
if(_line < 0) { _line=0;}\
switch(_line) { case 0:;
#define stop(V) } _line = 0; return (V); }
#define yield(V) \
do {\
_line=__LINE__;\
return (V); case __LINE__:;\
} while (0)
#endif // __generator_h_
Вот другой пример: сканируем последовательность:
generator(backward)
{
int *head;
int *tail;
backward(int *start, int *end ): head(start), tail(end){}
emit(int)
while(--tail > head)
yield(*tail);
stop(*tail);
};
int main(int argc, char* argv[])
{
int arr[] = {1,2,3,4,5,6};
backward scan(&arr[0],&arr[6]);
do
printf("got number %d\n", scan());
while(scan);
return 0;
}
Вот такие вот пироги.