Здравствуйте, remark, Вы писали:
CS>>В общем случае нужен stack on the heap.
CS>>Для C++ по всей видимости вполне себе будет достаточно объявления _generator как CRTP
CS>>структуры/шаблона плюс поле _generatror<NAME>* _stack.
CS>>Это точно будет работать — т.е. можно и рекурсивные вызовы делать (но только себя самого)
R>А можешь привести полную реализацию с примером использования. А то пока это всё не складывается в единое целое...
Вот generator с поддержкой restart — рекурсивный рестарт себя самого.
template<typename T>
struct _generator
{
T* _stack;
int _line;
_generator():_stack(0), _line(-1) {}
void _push() { T* n = new T; *n = *static_cast<T*>(this); _stack = n; }
bool _pop() { if(!_stack) return false; T* t = _stack; *static_cast<T*>(this) = *_stack; t->_stack = 0; delete t; return true; }
~_generator() { while(_pop()); }
};
#define $generator(NAME) struct NAME : public _generator<NAME>
#define $emit(T) bool operator()(T& _rv) { \
if(_line < 0) _line=0; \
$START: switch(_line) { case 0:;
#define $stop } _line = 0; if(_pop()) goto $START; return false; }
#define $restart(WITH) { _push(); _stack->_line = __LINE__; _line=0; WITH; goto $START; case __LINE__:; }
#define $yield(V) \
do {\
_line=__LINE__;\
_rv = (V); return true; case __LINE__:;\
} while (0)
Используется так (обход дерева):
struct node
{
int value;
node* next;
node* kid;
node(int v):value(v), next(0), kid(0) {}
node* foster( node* child ) { child->next = kid; kid = child; return child; }
};
$generator(scan)
{
node* n;
scan( node* root = 0 ): n(root) {}
$emit(int)
for(;n; n = n->next)
{
$yield(n->value);
if( n->kid )
$restart( n = n->kid );
}
$stop
};
int main(int argc, char* argv[])
{
node * root = new node(0);
root->foster(new node(1));
root->foster(new node(2));
root->foster(new node(3));
root->foster(new node(4));
node * child5 = root->foster(new node(5));
root->foster(new node(6));
root->foster(new node(7));
root->foster(new node(8));
root->foster(new node(9));
child5->foster(new node(50));
child5->foster(new node(51));
child5->foster(new node(52));
child5->foster(new node(53));
scan g(root);
for(int n; g(n);)
printf("n = %d\n",n);
return 0;
}
Усовершенствования возможны.